Files
assistant-storefront/app/javascript/shared/components/OrderDetail.vue
Liang XJ 092fb2e083
Some checks failed
Lock Threads / action (push) Has been cancelled
Mark stale issues and pull requests / stale (push) Has been cancelled
Publish Chatwoot EE docker images / build (linux/amd64, ubuntu-latest) (push) Has been cancelled
Publish Chatwoot EE docker images / build (linux/arm64, ubuntu-22.04-arm) (push) Has been cancelled
Publish Chatwoot EE docker images / merge (push) Has been cancelled
Publish Chatwoot CE docker images / build (linux/amd64, ubuntu-latest) (push) Has been cancelled
Publish Chatwoot CE docker images / build (linux/arm64, ubuntu-22.04-arm) (push) Has been cancelled
Publish Chatwoot CE docker images / merge (push) Has been cancelled
Run Chatwoot CE spec / lint-backend (push) Has been cancelled
Run Chatwoot CE spec / lint-frontend (push) Has been cancelled
Run Chatwoot CE spec / frontend-tests (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (0, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (1, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (10, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (11, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (12, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (13, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (14, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (15, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (2, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (3, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (4, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (5, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (6, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (7, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (8, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (9, 16) (push) Has been cancelled
Run Linux nightly installer / nightly (push) Has been cancelled
Initial commit: Add logistics and order_detail message types
- Add Logistics component with progress tracking
- Add OrderDetail component for order information
- Support data-driven steps and actions
- Add blue color scale to widget SCSS
- Fix node overflow and progress bar rendering issues
- Add English translations for dashboard components

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-26 11:16:56 +08:00

182 lines
5.5 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<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) {
// 如果有 URL在父窗口中打开
if (action && action.url) {
if (window.parent !== window) {
// 在 iframe 中,直接设置父窗口 location
window.parent.location.href = action.url;
} else {
// 不在 iframe 中,直接使用当前窗口
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"
:class="{
'text-n-slate-11 hover:bg-n-slate-2 dark:hover:bg-n-solid-2 border-r border-n-weak': action.style === 'default' || !action.style,
'text-n-blue-10 font-semibold hover:bg-n-blue-1 dark:hover:bg-n-solid-blue': action.style === 'primary'
}"
>
{{ 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>