Files
console-dev/app/components/config/ConfigDiskCard.vue
T

352 lines
13 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>
/** 磁盘容量选择卡:options 定义离散值或步长区间,v-model 保存容量,change 通知父级重算报价。 */
import "~/assets/styles/ConfigDiskCard.Dx9IqqQ_.css";
import { nextTick } from "vue";
import { toDisplayString } from "vue";
import { renderSlot } from "vue";
import { createCommentVNode } from "vue";
import { computed } from "vue";
import { createElementBlock } from "vue";
import { Fragment } from "vue";
import { createElementVNode } from "vue";
import { unref } from "vue";
import { defineComponent } from "vue";
import { createVNode } from "vue";
import { openBlock } from "vue";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
import inputnumber from "primevue/inputnumber";
var m = {
class: `storage-field`,
},
h = {
key: 0,
class: `storage-label`,
},
g = [`aria-label`],
_ = {
class: `storage-card-header`,
},
v = [`disabled`, `aria-label`],
y = {
class: `storage-unit`,
"aria-hidden": `true`,
},
b = [`aria-label`, `aria-valuetext`, `disabled`, `value`, `min`, `max`],
x = {
key: 0,
class: `storage-description`,
},
S = Object.assign(
_plugin_vue_export_helper_t(
defineComponent({
__name: `ConfigDiskCard`,
props: {
label: {},
hideLabel: {
type: Boolean,
},
title: {},
modelValue: {},
options: {
default: () => [],
},
unit: {
default: `GB`,
},
description: {},
disabled: {
type: Boolean,
},
removable: {
type: Boolean,
},
},
emits: [`update:modelValue`, `change`, `remove`],
setup(l, { emit: f }) {
let S = l,
C = f,
w = computed(() =>
S.options
.map((e) => {
let t = e.type === `step` || e.type === `total`,
n = Number(t ? (e.min_value ?? e.value) : e.value),
r = Number(
t ? (e.max_value ?? e.min_value ?? e.value) : e.value,
),
i = Number(e.step) > 0 ? Number(e.step) : 1;
return {
min: n,
max: n + Math.floor((r - n) / i + 1e-7) * i,
step: i,
};
})
.filter(
(e) =>
Number.isFinite(e.min) &&
Number.isFinite(e.max) &&
e.max >= e.min,
),
),
T = computed(() => Math.min(...w.value.map((e) => e.min))),
E = computed(() => Math.max(...w.value.map((e) => e.max))),
D = computed(() => T.value === E.value),
O = computed(() => Number(S.modelValue) || 0),
k = computed(() =>
D.value
? `容量 ${T.value} ${S.unit}`
: `容量 ${T.value}–${E.value} ${S.unit}`,
);
function A(e) {
// 在所有有效区间中寻找最近合法档位,不能只按全局 min/max 截断后提交任意数值。
let t = T.value,
n = 1 / 0;
for (let r of w.value) {
let i = Number(
Math.min(
r.max,
Math.max(
r.min,
r.min + Math.round((e - r.min) / r.step) * r.step,
),
).toFixed(8),
),
a = Math.abs(i - e);
a < n && ((t = i), (n = a));
}
return t;
}
function j(e, t = !0) {
if (
S.disabled ||
D.value ||
e === null ||
!Number.isFinite(e) ||
!w.value.length
)
return;
let n = A(e);
Number(S.modelValue) !== n &&
(C(`update:modelValue`, n), t && C(`change`));
}
function M(e) {
// 拖动时更新容量但不逐帧重算;结束交互由 N 单独发出 change。
let t = e.target,
n = Number(t.value);
(j(n, !1), (t.value = String(A(n))));
}
function N() {
!S.disabled && !D.value && C(`change`);
}
function P(e) {
// 方向键跨区间寻找下一合法档位,避免跨越不允许购买的容量空档。
let t = [`ArrowRight`, `ArrowUp`].includes(e.key)
? 1
: [`ArrowLeft`, `ArrowDown`].includes(e.key)
? -1
: 0;
if (!t || S.disabled || D.value) return;
e.preventDefault();
let n = O.value,
r = w.value.flatMap((e) => {
let r =
t > 0
? Math.max(
e.min,
e.min +
(Math.floor((n - e.min) / e.step + 1e-7) + 1) *
e.step,
)
: Math.min(
e.max,
e.min +
(Math.ceil((n - e.min) / e.step - 1e-7) - 1) * e.step,
);
return r >= e.min && r <= e.max ? [r] : [];
});
r.length && j(t > 0 ? Math.min(...r) : Math.max(...r));
}
function F() {
!S.disabled && S.removable && C(`remove`);
}
async function I(t) {
// PrimeVue 完成内部输入更新后再同步合法值与 aria 状态,避免显示值和实际容量不一致。
(await Promise.resolve(), await nextTick());
let n = t.originalEvent.target;
((n.value = String(O.value)),
n.setAttribute(`aria-valuenow`, String(O.value)));
}
function L(e) {
e.key === `ArrowUp` || e.key === `ArrowDown`
? (e.stopPropagation(),
P(e),
I({
originalEvent: e,
}))
: e.key === `Enter` &&
I({
originalEvent: e,
});
}
return (e, i) => {
let f = inputnumber;
return (
openBlock(),
createElementBlock(`div`, m, [
l.hideLabel
? createCommentVNode(``, !0)
: (openBlock(),
createElementBlock(`div`, h, toDisplayString(l.label), 1)),
createElementVNode(
`div`,
{
class: `storage-card`,
role: `group`,
"aria-label": l.label,
},
[
createElementVNode(`div`, _, [
createElementVNode(
`strong`,
null,
toDisplayString(l.title || `标准存储`),
1,
),
l.removable
? (openBlock(),
createElementBlock(
`button`,
{
key: 0,
class: `storage-remove`,
type: `button`,
disabled: l.disabled,
"aria-label": `删除${l.label}`,
onClick: F,
},
[
...(i[0] ||= [
createElementVNode(
`i`,
{
class: `pi pi-trash`,
"aria-hidden": `true`,
},
null,
-1,
),
]),
],
8,
v,
))
: createCommentVNode(``, !0),
]),
renderSlot(e.$slots, `type`, {}, void 0, !0),
renderSlot(
e.$slots,
`default`,
{},
() => [
unref(w).length
? (openBlock(),
createElementBlock(
Fragment,
{
key: 0,
},
[
createElementVNode(
`div`,
{
class: `storage-capacity`,
onKeydownCapture: L,
},
[
createVNode(
f,
{
"aria-label": l.label,
disabled: l.disabled || unref(D),
"model-value": unref(O),
min: unref(T),
max: unref(E),
"use-grouping": !1,
"onUpdate:modelValue": j,
onBlur: I,
},
null,
8,
[
`aria-label`,
`disabled`,
`model-value`,
`min`,
`max`,
],
),
createElementVNode(
`span`,
y,
toDisplayString(l.unit),
1,
),
],
32,
),
createElementVNode(
`input`,
{
class: `storage-slider`,
type: `range`,
"aria-label": `${l.label}容量滑块`,
"aria-valuetext": `${unref(O)} ${l.unit}`,
disabled: l.disabled || unref(D),
value: unref(O),
min: unref(T),
max: unref(E),
step: `any`,
onInput: M,
onChange: N,
onKeydown: P,
},
null,
40,
b,
),
],
64,
))
: createCommentVNode(``, !0),
],
!0,
),
l.description || unref(w).length
? (openBlock(),
createElementBlock(
`p`,
x,
toDisplayString(l.description || unref(k)),
1,
))
: createCommentVNode(``, !0),
renderSlot(e.$slots, `extra`, {}, void 0, !0),
],
8,
g,
),
renderSlot(e.$slots, `hint`, {}, void 0, !0),
])
);
};
},
}),
[[`__scopeId`, `data-v-83c644c5`]],
),
{
__name: `ConfigDiskCard`,
},
);
export {};
export default S;
</script>