Green Harbor vs. Golden District
Sunday · 7:30 PMBasketball
Harbor
District
查看市场信息,选择结果并组合包含收益估算的买卖票据。
选择安装方式,用法示例将同步更新导入路径。
首次使用时,将安装的 src/components/orvui/styles.css 导入项目样式入口。
market-cards.vue比较市场列表、检查赔率与收益,并收藏单张卡片。
On the radar
Demo markets · simulated prices
Sunday · 7:30 PMBasketball
Mid 6thMLB
Dec 31Economics
<script setup lang="ts">
import { h, ref } from "vue";
import { PredictionMarketCard } from "@/components/orvui/blocks/prediction-market";
import { Button } from "@/components/orvui/motion/button";
// Synthetic club emblems authored for this demonstration; no external team marks.
function badge(label: string, color: string) {
const svg = `<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64"><path fill="${color}" d="M32 3 57 17v30L32 61 7 47V17Z"/><path fill="none" stroke="white" stroke-opacity=".6" stroke-width="2" d="m32 9 20 11v24L32 55 12 44V20Z"/><text x="32" y="39" fill="white" text-anchor="middle" font-family="system-ui,sans-serif" font-size="21" font-weight="700">${label}</text></svg>`;
return "data:image/svg+xml," + encodeURIComponent(svg);
}
const boston = badge("GH", "#15803d"), lakers = badge("GD", "#b45309"), rays = badge("BB", "#2563eb"), braves = badge("RS", "#be123c");
const markets = [
{
id: "basketball",
title: "Green Harbor vs. Golden District",
category: "Basketball",
status: "Sunday · 7:30 PM",
volume: "$2.4M",
live: false,
image: boston,
history: [12, 18, 15, 26, 20, 32, 29, 38, 34, 48, 43, 58],
outcomes: [
{
id: "boston",
label: "Harbor",
probability: 0.51,
next: 0.56,
color: "#34d399",
image: boston,
},
{
id: "lakers",
label: "District",
probability: 0.49,
next: 0.44,
color: "#fbbf24",
image: lakers,
},
],
},
{
id: "baseball",
title: "Blue Bay vs. Rose Summit",
category: "MLB",
status: "Mid 6th",
volume: "$458K",
live: true,
image: rays,
history: [8, 12, 10, 19, 15, 28, 23, 34, 30, 40, 36, 45],
outcomes: [
{
id: "rays",
label: "Blue Bay",
probability: 0.46,
next: 0.52,
color: "#60a5fa",
image: rays,
},
{
id: "braves",
label: "Summit",
probability: 0.54,
next: 0.48,
color: "#fb7185",
image: braves,
},
],
},
{
id: "rates",
title: "Where will interest rates land by the end of the year?",
category: "Economics",
status: "Dec 31",
volume: "$347K",
live: false,
image:
badge("RB", "#475569"),
history: [15, 11, 17, 14, 24, 21, 30, 25, 32, 29, 39, 42],
outcomes: [
{
id: "below",
label: "Below 3.5%",
probability: 0.68,
next: 0.72,
color: "#34d399",
image: null,
},
{
id: "above",
label: "Above 4.0%",
probability: 0.23,
next: 0.18,
color: "#60a5fa",
image: null,
},
],
},
];
const updated = ref(false),
saved = ref<Record<string, boolean>>({});
const icon =
(url: string, classes: string, size = 32) =>
() =>
h("img", { src: url, alt: "", width: size, height: size, class: classes });
</script>
<template>
<div class="@container w-full max-w-3xl space-y-5">
<div class="flex items-center justify-between gap-3">
<div>
<p class="text-sm font-medium">On the radar</p>
<p class="mt-1 text-xs text-muted-foreground">
Demo markets · simulated prices
</p>
</div>
<Button
variant="secondary"
size="sm"
class="shrink-0"
@click="updated = !updated"
>Update odds</Button
>
</div>
<div class="grid auto-rows-fr gap-4 @min-[640px]:grid-cols-2">
<PredictionMarketCard
v-for="market in markets"
:key="market.id"
:title="market.title"
:category="market.category"
:status="market.status"
:live="market.live"
:icon="
icon(
market.image,
market.id === 'rates'
? 'size-full bg-white object-contain p-1'
: 'size-full object-contain p-1',
48,
)
"
:volume="market.volume"
:volume-history="market.history"
:bookmarked="saved[market.id] ?? false"
:outcomes="
market.outcomes.map((outcome) => ({
...outcome,
probability: updated ? outcome.next : outcome.probability,
icon: outcome.image
? icon(outcome.image, 'size-full object-contain p-0.5')
: undefined,
}))
"
@bookmark-change="saved = { ...saved, [market.id]: $event }"
/>
</div>
</div>
</template>
trade-ticket.vue选择结果并填写买卖数量,通过可见反馈查看订单状态。
Avg. Price 16.7¢
<script setup lang="ts">
import { ref } from "vue";
import { PredictionMarket, type PredictionMarketOrderValue } from "@/components/orvui/blocks/prediction-market";
const outcomes = [
{ id: "yes", label: "Yes", price: 0.167 },
{ id: "no", label: "No", price: 0.834 },
];
const order = ref<PredictionMarketOrderValue>({
mode: "buy",
outcomeId: "yes",
amount: "115",
});
</script>
<template>
<div class="flex w-full items-center justify-center">
<PredictionMarket
v-model="order"
:outcomes="outcomes"
:balance="500"
:positions="{ yes: 125, no: 48 }"
:quick-amounts="[1, 5, 10, 100]"
/>
</div>
</template>
需要由表单、路由或父组件管理时,绑定下列状态并接收对应更新。v-model 是属性与 update 事件的简写;值的类型应与 API 一致。
| 组件 | Vue 绑定 | 更新事件 |
|---|---|---|
PredictionMarket | v-modelPredictionMarketOrderValue | update:modelValue |
PredictionMarketCard | v-model:bookmarkedboolean | update:bookmarked |
可选受控属性未传入时,按组件文档的默认行为工作;不要用固定的 false 或空值代替未传入。异步请求和持久化在应用中处理,再把结果传回组件。
Market Cards
titlestring—icon?boolean | null | string | number | void | VNode<RendererNode, RendererElement, { [key: string]: any; }> | VNodeArrayChildren | ComponentOptions<any, any, any, ComputedOptions, MethodOptions, any, any, any, string, {}, {}, string, {}, {}, {}, string, ComponentProvideOptions> | FunctionalComponent<any, {}, any, {}> | ComponentPublicInstanceConstructor<any, any, any, any, ComputedOptions, MethodOptions>—category?string—volumestring—volumeHistory?number[]() => []status?string—live?booleanfalseoutcomesPredictionMarketCardOutcome[]—bookmarked?booleanundefineddefaultBookmarked?booleanfalseoutcomeClick[selection: PredictionMarketCardSelection]@outcomeClickupdate:bookmarked[bookmarked: boolean]@update:bookmarkedbookmarkChange[bookmarked: boolean]@bookmarkChangeTrade Ticket
outcomes?PredictionMarketOutcome[]() => [
{ id: "up", label: "Up", price: 0.09 },
{ id: "down", label: "Down", price: 0.91 },
]modelValue?PredictionMarketOrderValue—defaultValue?Partial<PredictionMarketOrderValue>—authenticated?booleantrueorderTypeLabel?string"Market"balance?number500positions?Record<string, number>() => ({ up: 24, down: 16 })quickAmounts?number[]() => [10, 50, 100, 500]minTrade?number1classNames?PredictionMarketClassNames—update:modelValue[value: PredictionMarketOrderValue]@update:modelValuevalueChange[value: PredictionMarketOrderValue]@valueChangetrade[order: PredictionMarketOrderValue, quote: PredictionMarketQuote]@tradesignIn[]@signIn为交互控件提供明确的无障碍名称。保留文档中的键盘路径、可见焦点与减少动态效果状态;自定义插槽应继续保留所替代部件的语义。
部分组件参考了开源作品,相关署名与独立许可请参阅 NOTICE。
更新于