feat: 二次元前端改版 + 后端账号plan探测/调度修复
This commit is contained in:
@@ -6,8 +6,15 @@ import Icon from './Icon.vue'
|
||||
const props = defineProps({ account: { type: Object, required: true } })
|
||||
const emit = defineEmits(['close', 'saved'])
|
||||
|
||||
// concurrency is only adjustable for custom upstreams — others are system-fixed.
|
||||
// concurrency is only adjustable for custom upstreams — others are system-fixed
|
||||
// (adobe is set from the plan on every quota refresh: 会员号 5 / 普号 1).
|
||||
const canEditConcurrency = props.account.type === 'custom'
|
||||
const fixedConcurrency =
|
||||
props.account.type === 'adobe'
|
||||
? (props.account.plan === 'free' ? 1 : Number(props.account.concurrency) || 5)
|
||||
: props.account.type === 'grok'
|
||||
? 10
|
||||
: 1
|
||||
|
||||
const weight = ref(Number(props.account.weight) || 0)
|
||||
const concurrency = ref(Number(props.account.concurrency) || 1)
|
||||
@@ -61,7 +68,7 @@ async function submit() {
|
||||
<div>
|
||||
<label class="lbl">并发数 <span class="text-white/35">{{ canEditConcurrency ? '(单账号)' : '(系统固定,不可调整)' }}</span></label>
|
||||
<input v-if="canEditConcurrency" v-model.number="concurrency" type="number" min="1" class="field" placeholder="1" />
|
||||
<input v-else :value="account.type === 'grok' ? 10 : 1" disabled class="field" />
|
||||
<input v-else :value="fixedConcurrency" disabled class="field" />
|
||||
</div>
|
||||
<p v-if="status" class="text-xs" :class="isError ? 'text-rose-400' : 'text-emerald-400'">{{ status }}</p>
|
||||
<div class="flex justify-end gap-2 pt-2">
|
||||
|
||||
@@ -25,6 +25,9 @@ const PATHS = {
|
||||
receipt: '<path d="M4 2v20l2-1 2 1 2-1 2 1 2-1 2 1 2-1 2 1V2l-2 1-2-1-2 1-2-1-2 1-2-1-2 1Z"/><path d="M16 8h-6a2 2 0 1 0 0 4h4a2 2 0 1 1 0 4H8"/><path d="M12 17.5v-11"/>',
|
||||
book: '<path d="M12 7v14"/><path d="M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z"/>',
|
||||
info: '<circle cx="12" cy="12" r="10"/><path d="M12 16v-4"/><path d="M12 8h.01"/>',
|
||||
music: '<path d="M9 18V5l12-2v13"/><circle cx="6" cy="18" r="3"/><circle cx="18" cy="16" r="3"/>',
|
||||
play: '<path d="m6 3 14 9-14 9V3Z"/>',
|
||||
pause: '<rect x="14" y="4" width="4" height="16" rx="1"/><rect x="6" y="4" width="4" height="16" rx="1"/>',
|
||||
}
|
||||
|
||||
defineProps({ name: { type: String, required: true } })
|
||||
|
||||
@@ -113,7 +113,7 @@ async function doSmartImport() {
|
||||
全粘进来即可,无需任何前缀。
|
||||
</p>
|
||||
<p class="text-xs text-rose-500 mb-3 leading-relaxed bg-rose-50 rounded px-3 py-2 border border-rose-200">
|
||||
📢 需要购买 Adobe 号请联系 QQ:432539
|
||||
📢 需要购买 Adobe 号请联系 QQ:28998306
|
||||
</p>
|
||||
<textarea v-model="input" rows="10"
|
||||
class="field font-mono text-xs resize-none"
|
||||
|
||||
@@ -176,7 +176,7 @@ async function submit() {
|
||||
|
||||
<!-- header -->
|
||||
<div class="flex flex-col items-center text-center mb-6">
|
||||
<div class="logo-halo mb-3"><Logo :size="44" class="rounded-[13px]" /></div>
|
||||
<div class="logo-halo mb-3"><Logo :size="44" /></div>
|
||||
<transition name="swap" mode="out-in">
|
||||
<div :key="mode">
|
||||
<h2 class="text-lg font-semibold tracking-tight text-[color:var(--fg)]">{{ heading.title }}</h2>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<script setup>
|
||||
// Vivid mark: a violet→fuchsia rounded badge with a faceted, folded "V".
|
||||
// Self-contained SVG so it renders identically on dark and light shells.
|
||||
// Vivid mark: an open spectrum ring (lens/aperture) around a folded "V", with a
|
||||
// shutter dot closing the gap — image + video in one glyph. Transparent
|
||||
// background so it reads on both the dark and light shells.
|
||||
// Each instance gets unique gradient ids (useId) so multiple logos on one
|
||||
// page don't share/clobber defs.
|
||||
import { useId } from 'vue'
|
||||
@@ -8,32 +9,33 @@ import { useId } from 'vue'
|
||||
defineProps({ size: { type: [Number, String], default: 40 } })
|
||||
|
||||
const uid = useId()
|
||||
const gBg = `vbg-${uid}`
|
||||
const gGloss = `vgl-${uid}`
|
||||
const gRing = `vring-${uid}`
|
||||
const gV = `vv-${uid}`
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<svg :width="size" :height="size" viewBox="0 0 48 48" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg" class="shrink-0">
|
||||
<defs>
|
||||
<linearGradient :id="gBg" x1="6" y1="4" x2="42" y2="44" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#a855f7" />
|
||||
<stop offset="0.55" stop-color="#7c3aed" />
|
||||
<stop offset="1" stop-color="#ec4899" />
|
||||
<linearGradient :id="gRing" x1="6" y1="6" x2="42" y2="42" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#e879f9" />
|
||||
<stop offset="0.5" stop-color="#8b5cf6" />
|
||||
<stop offset="1" stop-color="#38bdf8" />
|
||||
</linearGradient>
|
||||
<linearGradient :id="gGloss" x1="24" y1="2" x2="24" y2="30" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#ffffff" stop-opacity="0.28" />
|
||||
<stop offset="1" stop-color="#ffffff" stop-opacity="0" />
|
||||
<linearGradient :id="gV" x1="14" y1="14" x2="34" y2="34" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#f0abfc" />
|
||||
<stop offset="1" stop-color="#8b5cf6" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
|
||||
<!-- badge -->
|
||||
<rect x="2" y="2" width="44" height="44" rx="13" :fill="`url(#${gBg})`" />
|
||||
<!-- top gloss for depth -->
|
||||
<rect x="2" y="2" width="44" height="22" rx="13" :fill="`url(#${gGloss})`" />
|
||||
|
||||
<!-- faceted V: left arm brighter, right arm dimmer -> folded look -->
|
||||
<path d="M12 15 H19 L24 26 L24 37 Z" fill="#ffffff" fill-opacity="0.95" />
|
||||
<path d="M36 15 H29 L24 26 L24 37 Z" fill="#ffffff" fill-opacity="0.72" />
|
||||
<g transform="translate(24 24)">
|
||||
<!-- open ring: dash gap leaves room for the shutter dot -->
|
||||
<circle r="18.5" fill="none" :stroke="`url(#${gRing})`" stroke-width="3.2"
|
||||
stroke-linecap="round" stroke-dasharray="86 30" transform="rotate(-58)" />
|
||||
<!-- folded V -->
|
||||
<path d="M-8 -7.5 L0 9 L8 -7.5" fill="none" :stroke="`url(#${gV})`" stroke-width="4.8"
|
||||
stroke-linecap="round" stroke-linejoin="round" />
|
||||
<circle cx="13" cy="-13" r="3.4" fill="#38bdf8" />
|
||||
</g>
|
||||
</svg>
|
||||
</template>
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
<script setup>
|
||||
// Vivi — the platform's original chibi mascot. Pure inline SVG (no raster
|
||||
// asset, no external dependency), so it scales crisply and inherits the
|
||||
// pink/violet/sky brand palette. `size` sets the square px box; the halo of
|
||||
// twin-tails + a camera-lens hair ring ties her to the B-ring logo.
|
||||
import { computed } from 'vue'
|
||||
const props = defineProps({
|
||||
size: { type: [Number, String], default: 160 },
|
||||
float: { type: Boolean, default: true },
|
||||
uid: { type: String, default: () => 'm' + Math.random().toString(36).slice(2, 8) },
|
||||
})
|
||||
const px = computed(() => (typeof props.size === 'number' ? props.size + 'px' : props.size))
|
||||
const g = (k) => `${props.uid}-${k}`
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<svg :width="px" :height="px" viewBox="0 0 200 200" fill="none"
|
||||
:class="['mascot', { 'mascot-float': float }]" aria-hidden="true">
|
||||
<defs>
|
||||
<linearGradient :id="g('hair')" x1="0" y1="0" x2="1" y2="1">
|
||||
<stop offset="0" stop-color="#f0abfc" />
|
||||
<stop offset="0.55" stop-color="#c084fc" />
|
||||
<stop offset="1" stop-color="#818cf8" />
|
||||
</linearGradient>
|
||||
<linearGradient :id="g('eye')" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="0" stop-color="#7dd3fc" />
|
||||
<stop offset="1" stop-color="#a855f7" />
|
||||
</linearGradient>
|
||||
<linearGradient :id="g('ring')" x1="0" y1="0" x2="1" y2="1">
|
||||
<stop offset="0" stop-color="#f472b6" />
|
||||
<stop offset="0.5" stop-color="#a78bfa" />
|
||||
<stop offset="1" stop-color="#38bdf8" />
|
||||
</linearGradient>
|
||||
<radialGradient :id="g('glow')" cx="0.5" cy="0.5" r="0.5">
|
||||
<stop offset="0" stop-color="#e879f9" stop-opacity="0.55" />
|
||||
<stop offset="1" stop-color="#e879f9" stop-opacity="0" />
|
||||
</radialGradient>
|
||||
</defs>
|
||||
|
||||
<!-- soft aura -->
|
||||
<circle cx="100" cy="104" r="86" :fill="`url(#${g('glow')})`" />
|
||||
|
||||
<!-- back twin-tail -->
|
||||
<path d="M56 78 C22 84 20 140 44 168 C58 150 60 120 74 104 Z" :fill="`url(#${g('hair')})`" opacity="0.92" />
|
||||
<path d="M144 78 C178 84 180 140 156 168 C142 150 140 120 126 104 Z" :fill="`url(#${g('hair')})`" opacity="0.92" />
|
||||
|
||||
<!-- hair back mass -->
|
||||
<path d="M100 34 C60 34 44 66 46 100 C47 116 56 128 62 132 L138 132 C144 128 153 116 154 100 C156 66 140 34 100 34 Z"
|
||||
:fill="`url(#${g('hair')})`" />
|
||||
|
||||
<!-- face -->
|
||||
<path d="M64 92 C64 66 80 52 100 52 C120 52 136 66 136 92 C136 118 120 134 100 134 C80 134 64 118 64 92 Z"
|
||||
fill="#fff5fb" />
|
||||
<!-- fringe -->
|
||||
<path d="M62 92 C60 66 78 50 100 50 C122 50 140 66 138 92 C132 78 120 74 118 90 C112 74 100 72 100 72 C100 72 88 74 82 90 C80 74 68 78 62 92 Z"
|
||||
:fill="`url(#${g('hair')})`" />
|
||||
|
||||
<!-- ears blush -->
|
||||
<circle cx="76" cy="106" r="7" fill="#fbb6ce" opacity="0.75" />
|
||||
<circle cx="124" cy="106" r="7" fill="#fbb6ce" opacity="0.75" />
|
||||
|
||||
<!-- eyes -->
|
||||
<g>
|
||||
<ellipse cx="83" cy="98" rx="9" ry="12" :fill="`url(#${g('eye')})`" />
|
||||
<ellipse cx="117" cy="98" rx="9" ry="12" :fill="`url(#${g('eye')})`" />
|
||||
<circle cx="85.5" cy="93.5" r="3.2" fill="#fff" />
|
||||
<circle cx="119.5" cy="93.5" r="3.2" fill="#fff" />
|
||||
<circle cx="81" cy="101" r="1.6" fill="#fff" opacity="0.85" />
|
||||
<circle cx="115" cy="101" r="1.6" fill="#fff" opacity="0.85" />
|
||||
</g>
|
||||
<!-- brows / smile -->
|
||||
<path d="M74 84 q9 -5 18 -1" stroke="#c084fc" stroke-width="2.4" stroke-linecap="round" />
|
||||
<path d="M108 83 q9 -4 18 1" stroke="#c084fc" stroke-width="2.4" stroke-linecap="round" />
|
||||
<path d="M92 114 q8 7 16 0" stroke="#f472b6" stroke-width="2.6" stroke-linecap="round" fill="none" />
|
||||
|
||||
<!-- camera-lens hair ring (echoes the logo) -->
|
||||
<g transform="translate(140 58)">
|
||||
<circle r="15" fill="none" :stroke="`url(#${g('ring')})`" stroke-width="4"
|
||||
stroke-linecap="round" stroke-dasharray="70 24" transform="rotate(-55)" />
|
||||
<circle r="5.5" fill="#38bdf8" />
|
||||
<circle r="2.2" fill="#fff" opacity="0.9" />
|
||||
</g>
|
||||
|
||||
<!-- sparkles -->
|
||||
<g fill="#fef08a">
|
||||
<path d="M46 60 l2.2 5 5 2.2 -5 2.2 -2.2 5 -2.2 -5 -5 -2.2 5 -2.2 Z" />
|
||||
<path d="M158 128 l1.6 3.6 3.6 1.6 -3.6 1.6 -1.6 3.6 -1.6 -3.6 -3.6 -1.6 3.6 -1.6 Z" />
|
||||
</g>
|
||||
<circle cx="52" cy="150" r="2.4" fill="#7dd3fc" />
|
||||
<circle cx="150" cy="44" r="2" fill="#f0abfc" />
|
||||
</svg>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.mascot { display: block; }
|
||||
.mascot-float { animation: mascotFloat 5s ease-in-out infinite; transform-origin: center; }
|
||||
@keyframes mascotFloat {
|
||||
0%, 100% { transform: translateY(0) rotate(-1deg); }
|
||||
50% { transform: translateY(-8px) rotate(1.5deg); }
|
||||
}
|
||||
@media (prefers-reduced-motion: reduce) { .mascot-float { animation: none; } }
|
||||
</style>
|
||||
Reference in New Issue
Block a user