|
@@ -0,0 +1,1148 @@
|
|
|
+<template>
|
|
|
+ <view class="customer-service-page">
|
|
|
+ <!-- 顶部栏 -->
|
|
|
+ <!-- 顶部导航栏 -->
|
|
|
+ <view class="custom-navbar">
|
|
|
+ <view class="navbar-left">
|
|
|
+ <text class="fa fa-angle-left" @click="goBack"></text>
|
|
|
+ <view class="navbar-title one-omit">
|
|
|
+ 时间是一种解药时间是一种解药时间是一种解药时间是一种解药时间是一种解药
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <view class="navbar-right" @click="toggleDropdown">
|
|
|
+ <image src="@/static/icon/more2.png" style="width: 64rpx; height: 64rpx; margin-top: 15rpx"
|
|
|
+ mode="widthFix"></image>
|
|
|
+
|
|
|
+ <view class="dropdown-menu" v-if="showDropdown">
|
|
|
+ <view class="dropdown-item" @tap="handleOption('report')">举报内容</view>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <!-- 聊天内容区 -->
|
|
|
+ <scroll-view class="cs-chat-list" :scroll-y="true" :scroll-with-animation="true"
|
|
|
+ :scroll-into-view="scrollToView" :style="{
|
|
|
+ paddingBottom: (keyboardHeight ? keyboardHeight + 100 : 100) + 'rpx',
|
|
|
+ }">
|
|
|
+ <view v-for="(msg, idx) in chatList" :key="msg.id">
|
|
|
+ <view v-if="shouldShowTime(idx)" class="cs-time-bar">
|
|
|
+ <view class="cs-time-inner">{{ formatTime(msg.time) }}</view>
|
|
|
+ </view>
|
|
|
+ <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">
|
|
|
+ <image class="order-card-img" v-if="msg.order.main_image" :src="msg.order.main_image" mode="aspectFill" />
|
|
|
+ <view class="order-card-info">
|
|
|
+ <view class="order-card-title">{{ msg.order.title }}</view>
|
|
|
+ <view class="order-card-row" v-if="msg.order.orderNo">
|
|
|
+ <text class="order-card-label">订单编号</text>
|
|
|
+ <text class="order-card-value">{{ msg.order.orderNo }}</text>
|
|
|
+ </view>
|
|
|
+ <view class="order-card-row" v-if="msg.order.orderTime">
|
|
|
+ <text class="order-card-label">下单时间</text>
|
|
|
+ <text class="order-card-value">{{
|
|
|
+ msg.order.orderTime
|
|
|
+ }}</text>
|
|
|
+ </view>
|
|
|
+ <view class="order-card-btn-box">
|
|
|
+ <button class="order-card-btn" @click="goDetails( msg.order)">查看详情</button>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </template>
|
|
|
+ <template v-else>
|
|
|
+ <view :id="'msg-' + msg.id" :class="[
|
|
|
+ 'cs-msg-item',
|
|
|
+ msg.type === 'user' ? 'cs-msg-self' : 'cs-msg-other',
|
|
|
+ ]">
|
|
|
+ <image class="cs-avatar" :src="msg.avatar" />
|
|
|
+ <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="widthFix"
|
|
|
+ style="max-width: 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>
|
|
|
+ <view style="height: 200rpx; width: 100%"></view>
|
|
|
+ <view :id="'bottom-anchor'"></view>
|
|
|
+ <view v-if="adShow" :style="{ height: orderCardHeight + 'rpx' }"></view>
|
|
|
+ </scroll-view>
|
|
|
+
|
|
|
+ <!-- 底部输入栏 -->
|
|
|
+ <view class="cs-input-bar" :style="{ bottom: keyboardHeight + 'rpx' }">
|
|
|
+ <!-- 广告条 -->
|
|
|
+ <view class="order-card" v-if="adShow">
|
|
|
+ <view class="order-card-header">
|
|
|
+ <image class="order-card-img" :src=" orderCardData.main_image " mode="aspectFill" />
|
|
|
+ <view class="order-card-info">
|
|
|
+ <view class="order-card-title one-omit">{{ orderCardData.title }}</view>
|
|
|
+ <view class="order-card-btn-box">
|
|
|
+ <button class="order-card-btn" @click="sendOrderCardMsg()">
|
|
|
+ 发给客服
|
|
|
+ </button>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ <image class="order-card-close" @click="closeOrderCard" src="@/static/icon/wd_icon_guanbi.png"
|
|
|
+ mode="widthFix"></image>
|
|
|
+ </view>
|
|
|
+ <view class="order-card-row" v-if="orderCardData.orderNo">
|
|
|
+ <text class="order-card-label">订单编号</text>
|
|
|
+ <text class="order-card-value">{{ orderCardData.orderNo }}</text>
|
|
|
+ </view>
|
|
|
+ <view class="order-card-row" v-if="orderCardData.orderTime">
|
|
|
+ <text class="order-card-label">下单时间</text>
|
|
|
+ <text class="order-card-value">{{ orderCardData.orderTime }}</text>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <!-- 假输入框 -->
|
|
|
+ <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="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(1)">发送</view>
|
|
|
+ </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 }}
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+import permission from '@/common/permission.js';
|
|
|
+
|
|
|
+export default {
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ chatList: [],
|
|
|
+ inputValue: "",
|
|
|
+ pollTimer: null,
|
|
|
+ scrollToView: "bottom-anchor",
|
|
|
+ adShow: true,
|
|
|
+ keyboardHeight: 0,
|
|
|
+ inputFocused: false,
|
|
|
+ orderCardHeight: 260,
|
|
|
+ showEmojiPanel: false,
|
|
|
+ showDropdown: false,
|
|
|
+ emojiList: ["😀", "😁", "😂", "🤣", "😃", "😄", "😅", "😆", "😉", "😊", "😋", "😎", "😍", "😘", "🥰", "😗", "😙", "😚", "🙂", "🤗", "🤩", "🤔", "🤨", "😐", "😑", "😶", "🙄", "😏", "😣", "😥", "😮", "🤐", "😯", "😪", "😫", "🥱", "😴", "😌", "😛", "😜", "😝", "🤤", "😒", "😓", "😔", "😕", "🙃", "🤑", "😲", "☹️", "🙁", "😖", "😞", "😟", "😤", "😢", "😭", "😦", "😧", "😨", "😩", "🤯", "😬", "😰", "😱", "🥵", "🥶", "😳", "🤪", "😵", "😡", "😠", "🤬", "😷", "🤒", "🤕", "🤢", "🤮", "🥴", "😇", "🥳", "🥺", "🤠", "😈", "👿", "👹", "👺", "💀", "👻", "👽", "🤖", "💩", "😺", "😸", "😹", "😻", "😼", "😽", "🙀", "😿", "😾", "🙈", "🙉", "🙊", "💋", "💌", "💘", "💝", "💖", "💗", "💓", "💞", "💕", "💟", "❣️", "💔", "❤️", "🧡", "💛", "💚", "💙", "💜", "🤎", "🖤", "🤍", "💯", "💢", "💥", "💫", "💦", "💨", "🕳️", "💣", "💬", "👋", "🤚", "🖐️", "✋", "🖖", "👌", "🤏", "✌️", "🤞", "🤟", "🤘", "🤙", "👈", "👉", "👆", "🖕", "👇", "☝️", "👍", "👎", "✊", "👊", "🤛", "🤜", "👏", "🙌", "👐", "🤲", "🙏", "✍️", "💅", "🤳", "💪", "🦾", "🦵", "🦶", "👂", "👃", "🧠", "🦷", "🦴", "��", "👁️", "👅", "👄"],
|
|
|
+ conversationId: 0,
|
|
|
+ creatorId: 0,
|
|
|
+ zcId: 0,
|
|
|
+ lastMsgId: 0,
|
|
|
+ pageSize: 20,
|
|
|
+ userInfo: {},
|
|
|
+ showRealInput: false, // 控制显示真输入框还是假输入框
|
|
|
+ orderCardData: {},
|
|
|
+ };
|
|
|
+ },
|
|
|
+ onLoad(options) {
|
|
|
+ this.creatorId = options.id || 0;
|
|
|
+ this.zcId = options.zc_id || 0;
|
|
|
+ this.fetchMessages();
|
|
|
+ this.startPolling();
|
|
|
+ this.getOrderCardData()
|
|
|
+ },
|
|
|
+ onHide() {
|
|
|
+ this.clearPolling();
|
|
|
+ },
|
|
|
+ onUnload() {
|
|
|
+ this.clearPolling();
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ goBack() {
|
|
|
+ uni.navigateBack();
|
|
|
+ },
|
|
|
+ // 轮询获取消息
|
|
|
+ startPolling() {
|
|
|
+ this.clearPolling();
|
|
|
+ this.pollTimer = setInterval(() => this.fetchMessages(false), 5000);
|
|
|
+ this.fetchMessages(false);
|
|
|
+ },
|
|
|
+ clearPolling() {
|
|
|
+ if (this.pollTimer) {
|
|
|
+ clearInterval(this.pollTimer);
|
|
|
+ this.pollTimer = null;
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 获取消息
|
|
|
+ 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.zcId
|
|
|
+ },
|
|
|
+ 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 => {
|
|
|
+ let returnValue= {
|
|
|
+ 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
|
|
|
+ }
|
|
|
+ if (msg.message_type == 5) {
|
|
|
+ returnValue.order = JSON.parse(msg.content);
|
|
|
+ }
|
|
|
+ return returnValue;
|
|
|
+ });
|
|
|
+ console.log(msgList, "消息列表");
|
|
|
+ // 合并未上传完成的临时消息
|
|
|
+ const tempMsgs = this.chatList.filter(m => m.uploading);
|
|
|
+ let newList;
|
|
|
+ if (isAppend) {
|
|
|
+ newList = [...msgList, ...this.chatList.filter(m => !m.uploading), ...tempMsgs];
|
|
|
+ } else {
|
|
|
+ newList = [...msgList, ...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(message_type ) {
|
|
|
+
|
|
|
+ if (!this.inputValue.trim() && message_type == 1) return;
|
|
|
+ const content = this.inputValue;
|
|
|
+ this.inputValue = "";
|
|
|
+ console.log(content, "发送消息",message_type);
|
|
|
+
|
|
|
+ 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: message_type, // 文本
|
|
|
+ content: content,
|
|
|
+ zc_id: this.zcId
|
|
|
+ },
|
|
|
+ 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' });
|
|
|
+ }
|
|
|
+ });
|
|
|
+ },
|
|
|
+ closeOrderCard() {
|
|
|
+ this.adShow = false;
|
|
|
+ },
|
|
|
+ shouldShowTime(idx) {
|
|
|
+ if (idx === 0) return true;
|
|
|
+ // 找到上一个显示时间条的消息
|
|
|
+ let lastShowIdx = -1;
|
|
|
+ for (let i = idx - 1; i >= 0; i--) {
|
|
|
+ if (this.shouldShowTime(i)) {
|
|
|
+ lastShowIdx = i;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (lastShowIdx === -1) return true;
|
|
|
+ const curTime = new Date(
|
|
|
+ this.chatList[idx].time.replace(/-/g, "/")
|
|
|
+ ).getTime();
|
|
|
+ const lastTime = new Date(
|
|
|
+ this.chatList[lastShowIdx].time.replace(/-/g, "/")
|
|
|
+ ).getTime();
|
|
|
+ // 20分钟 = 20*60*1000 毫秒
|
|
|
+ return curTime - lastTime > 20 * 60 * 1000;
|
|
|
+ },
|
|
|
+ formatTime(timeStr) {
|
|
|
+ // 例:'2025-05-21 20:01' => '05月21日 20:01'
|
|
|
+ if (!timeStr) return "";
|
|
|
+ const d = new Date(timeStr.replace(/-/g, "/"));
|
|
|
+ const MM = String(d.getMonth() + 1).padStart(2, "0");
|
|
|
+ const DD = String(d.getDate()).padStart(2, "0");
|
|
|
+ const hhmm = timeStr.slice(11, 16);
|
|
|
+ return `${MM}月${DD}日 ${hhmm}`;
|
|
|
+ },
|
|
|
+ onInputFocus(e) {
|
|
|
+ this.inputFocused = true;
|
|
|
+ },
|
|
|
+ onInputBlur(e) {
|
|
|
+ this.inputFocused = false;
|
|
|
+ this.keyboardHeight = 0;
|
|
|
+ },
|
|
|
+ px2rpx(px) {
|
|
|
+ // 以750设计稿为例,1rpx = 屏幕宽度/750
|
|
|
+ const screenWidth = uni.getSystemInfoSync().windowWidth;
|
|
|
+ return (px * 750) / screenWidth;
|
|
|
+ },
|
|
|
+ onKeyboardHeightChange(e) {
|
|
|
+ let pxHeight = e.detail ? e.detail.height : e.height || 0;
|
|
|
+ // #ifdef H5 || APP-PLUS
|
|
|
+ this.keyboardHeight = this.px2rpx(pxHeight);
|
|
|
+ // #endif
|
|
|
+ // #ifdef MP-WEIXIN
|
|
|
+ this.keyboardHeight = pxHeight; // 小程序下直接用rpx
|
|
|
+ // #endif
|
|
|
+ },
|
|
|
+ toggleEmojiPanel() {
|
|
|
+ this.inputFocused = false;
|
|
|
+ setTimeout(() => {
|
|
|
+ this.showEmojiPanel = !this.showEmojiPanel;
|
|
|
+ }, 100);
|
|
|
+ },
|
|
|
+ selectEmoji(emoji) {
|
|
|
+ this.inputValue += emoji;
|
|
|
+ this.showEmojiPanel = false;
|
|
|
+ },
|
|
|
+ sendOrderCardMsg() {
|
|
|
+ this.chatList.push({
|
|
|
+ id: Date.now(),
|
|
|
+ message_type: 5,
|
|
|
+ avatar: this.avatar, // 用户头像
|
|
|
+ order: {
|
|
|
+ img: "/static/crowdFunding/top-img.png",
|
|
|
+ title: "【Woh】灯塔 塔罗牌 治愈风泛伟特系",
|
|
|
+ orderNo: "12201544521215415415415",
|
|
|
+ orderTime: "2025-05-27 09:35:30",
|
|
|
+ },
|
|
|
+ time: this.getNowTime(),
|
|
|
+ });
|
|
|
+ this.sendMsg(5);
|
|
|
+
|
|
|
+
|
|
|
+ this.$nextTick(() => {
|
|
|
+ this.closeOrderCard();
|
|
|
+ setTimeout(() => {
|
|
|
+ this.scrollToView = "bottom-anchor";
|
|
|
+ }, 1000);
|
|
|
+ });
|
|
|
+ },
|
|
|
+ getNowTime() {
|
|
|
+ const d = new Date();
|
|
|
+ const pad = (n) => (n < 10 ? "0" + n : n);
|
|
|
+ return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(
|
|
|
+ d.getDate()
|
|
|
+ )} ${pad(d.getHours())}:${pad(d.getMinutes())}`;
|
|
|
+ },
|
|
|
+ // 切换下拉菜单显示状态
|
|
|
+ toggleDropdown() {
|
|
|
+ this.showDropdown = !this.showDropdown;
|
|
|
+ },
|
|
|
+ // 处理下拉菜单选项点击
|
|
|
+ handleOption(type) {
|
|
|
+ this.showDropdown = false;
|
|
|
+ switch (type) {
|
|
|
+ case 'report':
|
|
|
+ uni.navigateTo({
|
|
|
+ url: '/pages/my/feedback?isReportContent=true'
|
|
|
+ });
|
|
|
+ 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.zcId
|
|
|
+ },
|
|
|
+ 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' });
|
|
|
+ }
|
|
|
+ });
|
|
|
+ },
|
|
|
+ goDetails(item) {
|
|
|
+ console.log(item,'item');
|
|
|
+ let url = '';
|
|
|
+ if (item.orderNo) {
|
|
|
+ url='/pages/crowdFunding/orderDetails?id=' + item.orderNo;
|
|
|
+ }else{
|
|
|
+ url='/pages/crowdFunding/crowdfundingDetails?id=' + item.id;
|
|
|
+ }
|
|
|
+ uni.navigateTo({
|
|
|
+ url: url
|
|
|
+ });
|
|
|
+ },
|
|
|
+ getOrderCardData() {
|
|
|
+ if (this.zcId) {
|
|
|
+ uni.request({
|
|
|
+ url: this.$apiHost + '/crowdfund/detail',
|
|
|
+ method: 'GET',
|
|
|
+ data: {
|
|
|
+ id: this.zcId,
|
|
|
+ uuid: getApp().globalData.uuid,
|
|
|
+ skey: getApp().globalData.skey
|
|
|
+
|
|
|
+ },
|
|
|
+ success: (res) => {
|
|
|
+ if (res.data && res.data.success === 'yes' && res.data.data) {
|
|
|
+ this.orderCardData = res.data.data;
|
|
|
+ console.log(this.orderCardData,'this.orderCardData');
|
|
|
+ // 可根据接口返回字段设置isFavorite等
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 图片预览
|
|
|
+ previewImage(url) {
|
|
|
+ // 收集当前消息列表中的所有图片URL
|
|
|
+ const imageUrls = this.chatList
|
|
|
+ .filter(msg => msg.message_type === 2 && msg.media_url)
|
|
|
+ .map(msg => msg.media_url);
|
|
|
+ const currentIndex = imageUrls.indexOf(url);
|
|
|
+ uni.previewImage({
|
|
|
+ current: currentIndex >= 0 ? currentIndex : 0,
|
|
|
+ urls: imageUrls
|
|
|
+ });
|
|
|
+ },
|
|
|
+ },
|
|
|
+};
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="scss">
|
|
|
+.customer-service-page {
|
|
|
+ min-height: 100vh;
|
|
|
+ background: #f2f6f2;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ position: relative;
|
|
|
+
|
|
|
+ .custom-navbar {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: row;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: space-between;
|
|
|
+ height: 90rpx;
|
|
|
+ padding: 0 20rpx;
|
|
|
+ padding-top: var(--status-bar-height);
|
|
|
+ background-color: #ffffff;
|
|
|
+ position: sticky;
|
|
|
+ top: 0;
|
|
|
+ height: calc(90rpx + var(--status-bar-height));
|
|
|
+ z-index: 100;
|
|
|
+
|
|
|
+ .navbar-left {
|
|
|
+ height: 80rpx;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+
|
|
|
+ .fa-angle-left {
|
|
|
+ font-size: 48rpx;
|
|
|
+ color: #333;
|
|
|
+ }
|
|
|
+
|
|
|
+ .navbar-title {
|
|
|
+ max-width: 450rpx;
|
|
|
+ font-family: "PingFang SC-Bold";
|
|
|
+ font-weight: 400;
|
|
|
+ font-size: 32rpx;
|
|
|
+ color: #1f1f1f;
|
|
|
+ padding-left: 20rpx;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .navbar-right {
|
|
|
+ width: 80rpx;
|
|
|
+ height: 80rpx;
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+ align-items: center;
|
|
|
+
|
|
|
+ .fa-ellipsis-h {
|
|
|
+ font-size: 36rpx;
|
|
|
+ color: #333;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .cs-chat-list {
|
|
|
+ flex: 1;
|
|
|
+ padding: 24rpx 0 0 0;
|
|
|
+ overflow-y: auto;
|
|
|
+ background: #f6f7f9;
|
|
|
+
|
|
|
+ .cs-msg-item {
|
|
|
+ display: flex;
|
|
|
+ // align-items: flex-end;
|
|
|
+ margin-bottom: 18rpx;
|
|
|
+ padding: 0 24rpx;
|
|
|
+
|
|
|
+ &.cs-msg-other {
|
|
|
+ flex-direction: row;
|
|
|
+
|
|
|
+ .cs-avatar {
|
|
|
+ margin-right: 12rpx;
|
|
|
+ }
|
|
|
+
|
|
|
+ .cs-msg-bubble {
|
|
|
+ background: #fff;
|
|
|
+ color: #1f1f1f;
|
|
|
+ border-top-left-radius: 0;
|
|
|
+ border-top-right-radius: 12rpx;
|
|
|
+ border-bottom-left-radius: 12rpx;
|
|
|
+ border-bottom-right-radius: 12rpx;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ &.cs-msg-self {
|
|
|
+ flex-direction: row-reverse;
|
|
|
+
|
|
|
+ .cs-avatar {
|
|
|
+ margin-left: 12rpx;
|
|
|
+ }
|
|
|
+
|
|
|
+ .cs-msg-bubble {
|
|
|
+ background: #e6f6d9;
|
|
|
+ color: #1f1f1f;
|
|
|
+ border-top-right-radius: 0;
|
|
|
+ border-top-left-radius: 12rpx;
|
|
|
+ border-bottom-left-radius: 12rpx;
|
|
|
+ border-bottom-right-radius: 12rpx;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .cs-avatar {
|
|
|
+ width: 64rpx;
|
|
|
+ height: 64rpx;
|
|
|
+ border-radius: 50%;
|
|
|
+ }
|
|
|
+
|
|
|
+ .cs-msg-bubble {
|
|
|
+ max-width: 70vw;
|
|
|
+ min-height: 40rpx;
|
|
|
+ font-size: 28rpx;
|
|
|
+ padding: 18rpx 24rpx;
|
|
|
+ word-break: break-all;
|
|
|
+ box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.04);
|
|
|
+ margin-bottom: 2rpx;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .cs-time-bar {
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+ align-items: center;
|
|
|
+ margin: 18rpx 0 12rpx 0;
|
|
|
+
|
|
|
+ .cs-time-inner {
|
|
|
+ background: #fff;
|
|
|
+ color: #b2b2b2;
|
|
|
+ font-size: 24rpx;
|
|
|
+ border-radius: 16rpx;
|
|
|
+ padding: 8rpx 24rpx;
|
|
|
+ box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 2604);
|
|
|
+ display: inline-block;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .order-card {
|
|
|
+ background: #fff;
|
|
|
+ border-radius: 20rpx;
|
|
|
+ box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.04);
|
|
|
+ padding: 24rpx 24rpx 18rpx 24rpx;
|
|
|
+ margin: 24rpx;
|
|
|
+ position: absolute;
|
|
|
+ top: -26rpx;
|
|
|
+ transform: translateY(-100%);
|
|
|
+ font-size: 28rpx;
|
|
|
+ width: 670rpx;
|
|
|
+
|
|
|
+ .order-card-header {
|
|
|
+ display: flex;
|
|
|
+ align-items: flex-start;
|
|
|
+ position: relative;
|
|
|
+
|
|
|
+ .order-card-img {
|
|
|
+ width: 100rpx;
|
|
|
+ height: 100rpx;
|
|
|
+ border-radius: 12rpx;
|
|
|
+ margin-right: 18rpx;
|
|
|
+ flex-shrink: 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ .order-card-info {
|
|
|
+ flex: 1;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ justify-content: flex-start;
|
|
|
+
|
|
|
+ .order-card-title {
|
|
|
+ font-size: 30rpx;
|
|
|
+ color: #1f1f1f;
|
|
|
+ font-weight: 500;
|
|
|
+ margin-bottom: 18rpx;
|
|
|
+ margin-top: 2rpx;
|
|
|
+ line-height: 1.3;
|
|
|
+ max-width: 450rpx;
|
|
|
+ }
|
|
|
+
|
|
|
+ .order-card-btn-box {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: flex-end;
|
|
|
+
|
|
|
+ .order-card-btn {
|
|
|
+ font-family: "PingFang SC-Bold";
|
|
|
+ font-weight: 400;
|
|
|
+ font-size: 24rpx;
|
|
|
+ color: #acf934;
|
|
|
+ background: #1f1f1f;
|
|
|
+ border-radius: 128rpx;
|
|
|
+ padding: 8rpx 14rpx;
|
|
|
+ line-height: 1.2;
|
|
|
+ margin: 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .order-card-close {
|
|
|
+ position: absolute;
|
|
|
+ right: -10rpx;
|
|
|
+ top: -10rpx;
|
|
|
+ font-size: 36rpx;
|
|
|
+ color: #1f1f1f;
|
|
|
+ background: #fff;
|
|
|
+ border-radius: 50%;
|
|
|
+ width: 34rpx;
|
|
|
+ height: 34rpx;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ z-index: 2;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .order-card-row {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ margin-top: 12rpx;
|
|
|
+
|
|
|
+ .order-card-label {
|
|
|
+ color: #b2b2b2;
|
|
|
+ font-size: 26rpx;
|
|
|
+ width: 140rpx;
|
|
|
+ flex-shrink: 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ .order-card-value {
|
|
|
+ color: #1f1f1f;
|
|
|
+ font-size: 26rpx;
|
|
|
+ margin-left: 12rpx;
|
|
|
+ word-break: break-all;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .cs-input-bar {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ background: #fff;
|
|
|
+ padding: 12rpx 16rpx;
|
|
|
+ border-top: 1rpx solid #ededed;
|
|
|
+ position: fixed;
|
|
|
+ left: 0;
|
|
|
+ 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;
|
|
|
+ flex: 1;
|
|
|
+
|
|
|
+ .cs-textarea {
|
|
|
+ flex: 1;
|
|
|
+ min-height: 64rpx;
|
|
|
+ max-height: 120rpx;
|
|
|
+ overflow-y: auto;
|
|
|
+ border: none;
|
|
|
+ font-size: 28rpx;
|
|
|
+ background: #f6f7f9;
|
|
|
+ border-radius: 24rpx;
|
|
|
+ padding: 12rpx 20rpx;
|
|
|
+ resize: none;
|
|
|
+ width: 100%;
|
|
|
+ }
|
|
|
+
|
|
|
+ .bottom-bar {
|
|
|
+ width: 100%;
|
|
|
+ padding: 12rpx 0;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: space-between;
|
|
|
+ }
|
|
|
+
|
|
|
+ .send_btn {
|
|
|
+ background: #a6e22e;
|
|
|
+ color: #fff;
|
|
|
+ border-radius: 32rpx;
|
|
|
+ font-size: 28rpx;
|
|
|
+ padding: 26rpx 32rpx;
|
|
|
+ line-height: 0;
|
|
|
+ border: 1rpx solid transparent;
|
|
|
+
|
|
|
+ &.prohibit {
|
|
|
+ background: #fff;
|
|
|
+ border: 1rpx solid #999;
|
|
|
+ color: #999;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .emoji-panel {
|
|
|
+ position: fixed;
|
|
|
+ left: 0;
|
|
|
+ right: 0;
|
|
|
+ bottom: 0;
|
|
|
+ z-index: 1000;
|
|
|
+ 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;
|
|
|
+ height: 60rpx;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ font-size: 36rpx;
|
|
|
+ color: #333;
|
|
|
+ margin: 8rpx;
|
|
|
+ border-radius: 8rpx;
|
|
|
+ padding: 8rpx;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .cs-msg-order-card-box {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: row-reverse;
|
|
|
+
|
|
|
+ .order-card-avatar {
|
|
|
+ width: 64rpx;
|
|
|
+ height: 64rpx;
|
|
|
+ border-radius: 50%;
|
|
|
+ margin-left: 12rpx;
|
|
|
+ margin-right: 24rpx;
|
|
|
+ }
|
|
|
+
|
|
|
+ .cs-msg-order-card {
|
|
|
+ position: relative;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: row;
|
|
|
+ align-items: flex-start;
|
|
|
+ background: #fff;
|
|
|
+ border-radius: 20rpx;
|
|
|
+ box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.04);
|
|
|
+ padding: 24rpx 24rpx 18rpx 24rpx;
|
|
|
+ margin: 24rpx 0 0 0;
|
|
|
+ width: 600rpx;
|
|
|
+ min-height: 160rpx;
|
|
|
+
|
|
|
+ .order-card-img {
|
|
|
+ width: 100rpx;
|
|
|
+ height: 100rpx;
|
|
|
+ border-radius: 12rpx;
|
|
|
+ margin-right: 18rpx;
|
|
|
+ flex-shrink: 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ .order-card-info {
|
|
|
+ flex: 1;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ justify-content: flex-start;
|
|
|
+
|
|
|
+ .order-card-title {
|
|
|
+ font-size: 30rpx;
|
|
|
+ color: #1f1f1f;
|
|
|
+ font-weight: 500;
|
|
|
+ margin-bottom: 18rpx;
|
|
|
+ margin-top: 2rpx;
|
|
|
+ line-height: 1.3;
|
|
|
+ max-width: 350rpx;
|
|
|
+ word-break: break-all;
|
|
|
+ }
|
|
|
+
|
|
|
+ .order-card-btn-box {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: flex-end;
|
|
|
+ margin-top: 12rpx;
|
|
|
+
|
|
|
+ .order-card-btn {
|
|
|
+ font-family: "PingFang SC-Bold";
|
|
|
+ font-weight: 400;
|
|
|
+ font-size: 24rpx;
|
|
|
+ color: #1f1f1f;
|
|
|
+ background: #acf934;
|
|
|
+ border-radius: 128rpx;
|
|
|
+ padding: 8rpx 24rpx;
|
|
|
+ line-height: 1.2;
|
|
|
+ margin: 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .order-card-row {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ margin-top: 8rpx;
|
|
|
+
|
|
|
+ .order-card-label {
|
|
|
+ color: #b2b2b2;
|
|
|
+ font-size: 26rpx;
|
|
|
+ width: 140rpx;
|
|
|
+ flex-shrink: 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ .order-card-value {
|
|
|
+ color: #1f1f1f;
|
|
|
+ font-size: 26rpx;
|
|
|
+ margin-left: 12rpx;
|
|
|
+ word-break: break-all;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .dropdown-menu {
|
|
|
+ position: absolute;
|
|
|
+ top: calc(100% + 10rpx);
|
|
|
+ right: 20rpx;
|
|
|
+ background-color: #ffffff;
|
|
|
+ border-radius: 20rpx;
|
|
|
+ padding: 0;
|
|
|
+ width: 200rpx;
|
|
|
+ box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.1);
|
|
|
+ z-index: 100;
|
|
|
+ transform-origin: top right;
|
|
|
+ animation: dropdownAnimation 0.2s ease-out;
|
|
|
+ overflow: hidden;
|
|
|
+
|
|
|
+ .dropdown-item {
|
|
|
+ padding: 24rpx 0;
|
|
|
+ color: #333333;
|
|
|
+ font-size: 28rpx;
|
|
|
+ position: relative;
|
|
|
+ text-align: center;
|
|
|
+
|
|
|
+ &:not(:last-child)::after {
|
|
|
+ content: '';
|
|
|
+ position: absolute;
|
|
|
+ left: 0;
|
|
|
+ right: 0;
|
|
|
+ bottom: 0;
|
|
|
+ height: 1rpx;
|
|
|
+ background-color: #EEEEEE;
|
|
|
+ }
|
|
|
+
|
|
|
+ &:active {
|
|
|
+ background-color: #f8f8f8;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @keyframes dropdownAnimation {
|
|
|
+ 0% {
|
|
|
+ opacity: 0;
|
|
|
+ transform: scale(0.95) translateY(-5rpx);
|
|
|
+ }
|
|
|
+
|
|
|
+ 100% {
|
|
|
+ opacity: 1;
|
|
|
+ transform: scale(1) translateY(0);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+</style>
|