Files
assistant-storefront/app/javascript/shared/components/OrderDetail.vue

193 lines
5.8 KiB
Vue
Raw Normal View History

<script>
import { mapActions } from 'vuex';
export default {
name: 'OrderDetail',
props: {
status: { type: String, default: 'completed' },
statusText: { type: String, default: '已完成' },
statusColor: { type: String, default: 'text-green-600' },
orderId: { type: [String, Number], required: true },
orderTime: { type: String, required: true },
items: {
type: Array,
default: () => [],
},
actions: {
type: Array,
default: () => [],
},
showTotal: { type: Boolean, default: true },
totalLabel: { type: String, default: '' },
amountLabel: { type: String, default: '' },
},
computed: {
totalQuantity() {
return this.items.reduce((sum, item) => sum + item.quantity, 0);
},
},
methods: {
...mapActions('conversation', ['sendMessage']),
isTailwindColor(color) {
// 判断是否是 Tailwind class包含 text-、bg-、fg- 等)
return color && (color.includes('text-') || color.includes('bg-') || color.includes('fg-'));
},
getInlineColor(color) {
if (!color || this.isTailwindColor(color)) return {};
return { color };
},
getSingleColor(color) {
// 从 Tailwind class 或十六进制提取颜色值用于圆点背景
if (!color) return '#10b981';
if (this.isTailwindColor(color)) {
// Tailwind color mapping
const colorMap = {
'text-green-600': '#10b981',
'text-green-500': '#10b981',
'text-blue-600': '#2563eb',
'text-blue-500': '#3b82f6',
'text-orange-600': '#f59e0b',
'text-orange-500': '#f59e0b',
'text-red-600': '#dc2626',
'text-red-500': '#ef4444',
'text-gray-600': '#4b5563',
'text-gray-500': '#6b7280',
};
return colorMap[color] || '#10b981';
}
// 十六进制颜色直接返回
return color;
},
onActionClick(action) {
feat: add search_image and product_list content types with image upload ## 新增功能 ### 1. 新增消息类型 - 添加 search_image (17) 和 product_list (18) content_type - 支持图片搜索和商品列表消息展示 ### 2. 图片上传功能 - 添加 ImageUploadButton 组件,支持图片上传到 Mall API - 上传后发送 search_image 类型消息,图片 URL 存储在 content_attributes - 支持图片文件验证(类型、大小) ### 3. Webhook 推送优化 - 修改 webhook_listener.rb,允许 search_image 类型即使 content 为空也推送 webhook - 解决 search_image 消息不触发 webhook 的问题 ### 4. 前端组件 - 新增 SearchImage.vue 组件(widget 和 dashboard) - 新增 ProductList.vue、Logistics.vue、OrderDetail.vue、OrderList.vue 组件 - 更新 Message.vue 路由逻辑支持新的 content_type - 更新 UserMessage.vue 支持 search_image 消息显示 ### 5. API 层修改 - widget/messages_controller.rb: 允许 content_attributes 参数 - widget/base_controller.rb: 使用前端传入的 content_attributes - widget/conversation API: 支持 contentAttributes 参数传递 - conversation actions 和 helpers: 完整的 content_attributes 数据流 ### 6. Widget 测试页面优化 - 重写 /widget_tests 页面,支持游客/用户模式切换 - 登录流程:使用 reset() + setUser(),不刷新页面 - 退出流程:使用 reset() + 刷新页面 - 添加详细的日志输出和状态显示 ## 技术细节 ### Message Model ```ruby enum content_type: { # ...existing types... search_image: 17, product_list: 18 } ``` ### Webhook Listener ```ruby # Allow search_image webhook even if content is blank return if message.content.blank? && message.content_type != 'search_image' ``` ### Widget Upload Flow ``` 用户选择图片 → 上传到 Mall API → 获取图片 URL → 发送消息: { content: '', content_type: 'search_image', content_attributes: { url: '...' } } ``` Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-27 19:03:46 +08:00
// 如果有 URL根据 target 属性决定打开方式
if (action && action.url) {
feat: add search_image and product_list content types with image upload ## 新增功能 ### 1. 新增消息类型 - 添加 search_image (17) 和 product_list (18) content_type - 支持图片搜索和商品列表消息展示 ### 2. 图片上传功能 - 添加 ImageUploadButton 组件,支持图片上传到 Mall API - 上传后发送 search_image 类型消息,图片 URL 存储在 content_attributes - 支持图片文件验证(类型、大小) ### 3. Webhook 推送优化 - 修改 webhook_listener.rb,允许 search_image 类型即使 content 为空也推送 webhook - 解决 search_image 消息不触发 webhook 的问题 ### 4. 前端组件 - 新增 SearchImage.vue 组件(widget 和 dashboard) - 新增 ProductList.vue、Logistics.vue、OrderDetail.vue、OrderList.vue 组件 - 更新 Message.vue 路由逻辑支持新的 content_type - 更新 UserMessage.vue 支持 search_image 消息显示 ### 5. API 层修改 - widget/messages_controller.rb: 允许 content_attributes 参数 - widget/base_controller.rb: 使用前端传入的 content_attributes - widget/conversation API: 支持 contentAttributes 参数传递 - conversation actions 和 helpers: 完整的 content_attributes 数据流 ### 6. Widget 测试页面优化 - 重写 /widget_tests 页面,支持游客/用户模式切换 - 登录流程:使用 reset() + setUser(),不刷新页面 - 退出流程:使用 reset() + 刷新页面 - 添加详细的日志输出和状态显示 ## 技术细节 ### Message Model ```ruby enum content_type: { # ...existing types... search_image: 17, product_list: 18 } ``` ### Webhook Listener ```ruby # Allow search_image webhook even if content is blank return if message.content.blank? && message.content_type != 'search_image' ``` ### Widget Upload Flow ``` 用户选择图片 → 上传到 Mall API → 获取图片 URL → 发送消息: { content: '', content_type: 'search_image', content_attributes: { url: '...' } } ``` Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-27 19:03:46 +08:00
const target = action.target || '_self'; // 默认在当前窗口打开
if (window.parent !== window) {
feat: add search_image and product_list content types with image upload ## 新增功能 ### 1. 新增消息类型 - 添加 search_image (17) 和 product_list (18) content_type - 支持图片搜索和商品列表消息展示 ### 2. 图片上传功能 - 添加 ImageUploadButton 组件,支持图片上传到 Mall API - 上传后发送 search_image 类型消息,图片 URL 存储在 content_attributes - 支持图片文件验证(类型、大小) ### 3. Webhook 推送优化 - 修改 webhook_listener.rb,允许 search_image 类型即使 content 为空也推送 webhook - 解决 search_image 消息不触发 webhook 的问题 ### 4. 前端组件 - 新增 SearchImage.vue 组件(widget 和 dashboard) - 新增 ProductList.vue、Logistics.vue、OrderDetail.vue、OrderList.vue 组件 - 更新 Message.vue 路由逻辑支持新的 content_type - 更新 UserMessage.vue 支持 search_image 消息显示 ### 5. API 层修改 - widget/messages_controller.rb: 允许 content_attributes 参数 - widget/base_controller.rb: 使用前端传入的 content_attributes - widget/conversation API: 支持 contentAttributes 参数传递 - conversation actions 和 helpers: 完整的 content_attributes 数据流 ### 6. Widget 测试页面优化 - 重写 /widget_tests 页面,支持游客/用户模式切换 - 登录流程:使用 reset() + setUser(),不刷新页面 - 退出流程:使用 reset() + 刷新页面 - 添加详细的日志输出和状态显示 ## 技术细节 ### Message Model ```ruby enum content_type: { # ...existing types... search_image: 17, product_list: 18 } ``` ### Webhook Listener ```ruby # Allow search_image webhook even if content is blank return if message.content.blank? && message.content_type != 'search_image' ``` ### Widget Upload Flow ``` 用户选择图片 → 上传到 Mall API → 获取图片 URL → 发送消息: { content: '', content_type: 'search_image', content_attributes: { url: '...' } } ``` Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-27 19:03:46 +08:00
// 在 iframe 中
if (target === '_blank') {
window.parent.open(action.url, '_blank');
} else {
window.parent.location.href = action.url;
}
} else {
feat: add search_image and product_list content types with image upload ## 新增功能 ### 1. 新增消息类型 - 添加 search_image (17) 和 product_list (18) content_type - 支持图片搜索和商品列表消息展示 ### 2. 图片上传功能 - 添加 ImageUploadButton 组件,支持图片上传到 Mall API - 上传后发送 search_image 类型消息,图片 URL 存储在 content_attributes - 支持图片文件验证(类型、大小) ### 3. Webhook 推送优化 - 修改 webhook_listener.rb,允许 search_image 类型即使 content 为空也推送 webhook - 解决 search_image 消息不触发 webhook 的问题 ### 4. 前端组件 - 新增 SearchImage.vue 组件(widget 和 dashboard) - 新增 ProductList.vue、Logistics.vue、OrderDetail.vue、OrderList.vue 组件 - 更新 Message.vue 路由逻辑支持新的 content_type - 更新 UserMessage.vue 支持 search_image 消息显示 ### 5. API 层修改 - widget/messages_controller.rb: 允许 content_attributes 参数 - widget/base_controller.rb: 使用前端传入的 content_attributes - widget/conversation API: 支持 contentAttributes 参数传递 - conversation actions 和 helpers: 完整的 content_attributes 数据流 ### 6. Widget 测试页面优化 - 重写 /widget_tests 页面,支持游客/用户模式切换 - 登录流程:使用 reset() + setUser(),不刷新页面 - 退出流程:使用 reset() + 刷新页面 - 添加详细的日志输出和状态显示 ## 技术细节 ### Message Model ```ruby enum content_type: { # ...existing types... search_image: 17, product_list: 18 } ``` ### Webhook Listener ```ruby # Allow search_image webhook even if content is blank return if message.content.blank? && message.content_type != 'search_image' ``` ### Widget Upload Flow ``` 用户选择图片 → 上传到 Mall API → 获取图片 URL → 发送消息: { content: '', content_type: 'search_image', content_attributes: { url: '...' } } ``` Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-27 19:03:46 +08:00
// 不在 iframe 中
if (target === '_blank') {
window.open(action.url, '_blank');
} else {
window.location.href = action.url;
}
}
return;
}
// 否则发送消息
if (action && action.reply) {
this.sendMessage({
content: action.reply,
});
}
},
},
};
</script>
<template>
<div class="order-chat-card">
<!-- 头部状态单号下单时间 -->
<div class="px-3 pt-4 pb-2 bg-gray-50 border-b">
<div class="flex justify-between items-center">
<span class="text-xs font-bold flex items-center" :class="isTailwindColor(statusColor) ? statusColor : ''" :style="getInlineColor(statusColor)">
<span class="w-1.5 h-1.5 rounded-full mr-1.5" :style="{ backgroundColor: getSingleColor(statusColor) }"></span>
{{ statusText }}
</span>
<span class="text-xs text-gray-400 font-mono">ID: {{ orderId }}</span>
</div>
<div class="text-xs text-gray-400 mt-0.5">
📅 {{ orderTime }}
</div>
</div>
<!-- 商品滚动区域 -->
<div class="scroll-container p-2 space-y-2">
<div v-for="(item, index) in items" :key="index" class="flex items-center space-x-2">
<img
:src="item.image"
class="w-10 h-[50px] object-cover rounded border border-gray-100 flex-shrink-0 bg-gray-200 dark:bg-gray-700"
alt="product"
/>
<div class="flex-1 min-w-0">
<div class="text-xs font-medium text-gray-800 truncate">
{{ item.name }}
</div>
<div class="flex justify-between items-center">
<span class="text-xs text-gray-400 font-mono">x{{ item.quantity }}</span>
<span class="text-xs font-bold text-gray-700 font-mono">
{{ item.price }}
</span>
</div>
</div>
</div>
</div>
<!-- 价格总计 -->
<div v-if="showTotal" class="px-3 py-2 bg-red-50/50 border-t border-red-100">
<div class="flex justify-between items-baseline">
<span v-if="totalLabel" class="text-xs text-gray-500 font-medium">
{{ totalLabel }}
</span>
<span v-if="amountLabel" class="text-sm font-black text-red-600 font-mono">
{{ amountLabel }}
</span>
</div>
</div>
<!-- 操作按钮 -->
<div class="flex border-t border-n-weak" style="border-style: solid;">
<button
v-for="(action, index) in actions"
:key="index"
@click="onActionClick(action)"
class="flex-1 py-3 text-sm transition-colors"
feat: add search_image and product_list content types with image upload ## 新增功能 ### 1. 新增消息类型 - 添加 search_image (17) 和 product_list (18) content_type - 支持图片搜索和商品列表消息展示 ### 2. 图片上传功能 - 添加 ImageUploadButton 组件,支持图片上传到 Mall API - 上传后发送 search_image 类型消息,图片 URL 存储在 content_attributes - 支持图片文件验证(类型、大小) ### 3. Webhook 推送优化 - 修改 webhook_listener.rb,允许 search_image 类型即使 content 为空也推送 webhook - 解决 search_image 消息不触发 webhook 的问题 ### 4. 前端组件 - 新增 SearchImage.vue 组件(widget 和 dashboard) - 新增 ProductList.vue、Logistics.vue、OrderDetail.vue、OrderList.vue 组件 - 更新 Message.vue 路由逻辑支持新的 content_type - 更新 UserMessage.vue 支持 search_image 消息显示 ### 5. API 层修改 - widget/messages_controller.rb: 允许 content_attributes 参数 - widget/base_controller.rb: 使用前端传入的 content_attributes - widget/conversation API: 支持 contentAttributes 参数传递 - conversation actions 和 helpers: 完整的 content_attributes 数据流 ### 6. Widget 测试页面优化 - 重写 /widget_tests 页面,支持游客/用户模式切换 - 登录流程:使用 reset() + setUser(),不刷新页面 - 退出流程:使用 reset() + 刷新页面 - 添加详细的日志输出和状态显示 ## 技术细节 ### Message Model ```ruby enum content_type: { # ...existing types... search_image: 17, product_list: 18 } ``` ### Webhook Listener ```ruby # Allow search_image webhook even if content is blank return if message.content.blank? && message.content_type != 'search_image' ``` ### Widget Upload Flow ``` 用户选择图片 → 上传到 Mall API → 获取图片 URL → 发送消息: { content: '', content_type: 'search_image', content_attributes: { url: '...' } } ``` Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-27 19:03:46 +08:00
:class="[
action.style === 'primary'
? 'text-n-blue-10 font-semibold hover:bg-n-blue-1 dark:hover:bg-n-solid-blue'
: 'text-n-slate-11 hover:bg-n-slate-2 dark:hover:bg-n-solid-2',
index < actions.length - 1 ? 'border-r border-n-weak' : ''
]"
>
{{ action.text }}
</button>
</div>
</div>
</template>
<style scoped>
.order-chat-card {
max-width: 380px;
background: white;
border-radius: 12px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
overflow: hidden;
border: 1px solid #e5e7eb;
}
.scroll-container {
max-height: 210px;
overflow-y: auto;
}
/* 自定义滚动条 */
.scroll-container::-webkit-scrollbar {
width: 4px;
}
.scroll-container::-webkit-scrollbar-thumb {
background-color: #e5e7eb;
border-radius: 10px;
}
.scroll-container::-webkit-scrollbar-track {
background: transparent;
}
</style>