dev
This commit is contained in:
@@ -543,6 +543,7 @@ class Character(CharacterProperty):
|
|||||||
return res
|
return res
|
||||||
|
|
||||||
def calc_init(self, setInfo: dict[str, dict]):
|
def calc_init(self, setInfo: dict[str, dict]):
|
||||||
|
self.equ_options = setInfo.get('options', {})
|
||||||
# 打造信息导入
|
# 打造信息导入
|
||||||
self.SetDetail(setInfo)
|
self.SetDetail(setInfo)
|
||||||
# 技能等级设置
|
# 技能等级设置
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ from . import suit
|
|||||||
from .register import execture
|
from .register import execture
|
||||||
|
|
||||||
options = [
|
options = [
|
||||||
{'id': 1, 'name': '龙战八荒,', 'options': ['BUFF OFF', 'BUFF ON', '期望']},
|
{'id': 1, 'name': '龙战八荒', 'options': ['BUFF OFF', 'BUFF ON', '期望']},
|
||||||
{'id': 2, 'name': '混沌净化', 'options': ['净化', '堕落']},
|
{'id': 2, 'name': '混沌净化', 'options': ['净化', '堕落']},
|
||||||
{'id': 3, 'name': '群猎美学', 'options': ['单刷', '组队']},
|
{'id': 3, 'name': '群猎美学', 'options': ['单刷', '组队']},
|
||||||
{'id': 4, 'name': '魔攻核', 'options': ['普通', '追击']},
|
{'id': 4, 'name': '魔攻核', 'options': ['普通', '追击']},
|
||||||
|
|||||||
@@ -15,8 +15,6 @@
|
|||||||
"format": "prettier --write src/"
|
"format": "prettier --write src/"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@iconify/vue": "^4.3.0",
|
|
||||||
"@radix-ui/colors": "^3.0.0",
|
|
||||||
"@vueuse/core": "^12.8.2",
|
"@vueuse/core": "^12.8.2",
|
||||||
"axios": "^1.8.2",
|
"axios": "^1.8.2",
|
||||||
"hoci": "^0.6.0",
|
"hoci": "^0.6.0",
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ export default defineRequest((request) => {
|
|||||||
async calc(config: IConfig) {
|
async calc(config: IConfig) {
|
||||||
const res = await request.post<IResult>('/calc', config)
|
const res = await request.post<IResult>('/calc', config)
|
||||||
return res.data
|
return res.data
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
// Compare this snippet from frontend/src/api/common/index.ts:
|
// Compare this snippet from frontend/src/api/common/index.ts:
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ export interface IResult {
|
|||||||
buffer: boolean
|
buffer: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export interface IResultSkill {
|
export interface IResultSkill {
|
||||||
name: string
|
name: string
|
||||||
icon: string
|
icon: string
|
||||||
|
|||||||
@@ -37,14 +37,15 @@ export interface ICharacterInfo {
|
|||||||
avatar: Record<string, IAvatarInfo[]>
|
avatar: Record<string, IAvatarInfo[]>
|
||||||
jades: IJade[]
|
jades: IJade[]
|
||||||
sundry: Record<string, ISundry>
|
sundry: Record<string, ISundry>
|
||||||
|
options: { id: number; name: string; options: string[] }[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ISundry {
|
export interface ISundry {
|
||||||
id:number,
|
id: number
|
||||||
options: {
|
options: {
|
||||||
name:string,
|
name: string
|
||||||
value: number
|
value: number
|
||||||
}[],
|
}[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IEquipment {
|
export interface IEquipment {
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
export { default as NTooltip } from "./tooltip"
|
export { default as NTooltip } from './tooltip'
|
||||||
|
|||||||
@@ -1,42 +1,52 @@
|
|||||||
import { syncRefs, useVModel } from "@vueuse/core"
|
import { syncRefs, useVModel } from '@vueuse/core'
|
||||||
import type { CSSProperties, PropType } from "vue";
|
import type { CSSProperties, PropType } from 'vue'
|
||||||
import { Teleport, Transition, computed, defineComponent, nextTick, reactive, ref, renderSlot, watch } from "vue"
|
import {
|
||||||
import { provideShow } from "../hooks/show"
|
Teleport,
|
||||||
|
Transition,
|
||||||
|
computed,
|
||||||
|
defineComponent,
|
||||||
|
nextTick,
|
||||||
|
reactive,
|
||||||
|
ref,
|
||||||
|
renderSlot,
|
||||||
|
watch,
|
||||||
|
} from 'vue'
|
||||||
|
import { provideShow } from '../hooks/show'
|
||||||
|
|
||||||
export const tooltipProps = {
|
export const tooltipProps = {
|
||||||
popClass: {
|
popClass: {
|
||||||
type: String
|
type: String,
|
||||||
},
|
},
|
||||||
position: {
|
position: {
|
||||||
type: String as PropType<"bottom" | "top" | "left" | "right" | "auto">,
|
type: String as PropType<'bottom' | 'top' | 'left' | 'right' | 'auto'>,
|
||||||
default: () => "auto"
|
default: () => 'auto',
|
||||||
},
|
},
|
||||||
offset: {
|
offset: {
|
||||||
type: Number,
|
type: Number,
|
||||||
default: () => 8
|
default: () => 8,
|
||||||
},
|
},
|
||||||
lazy: {
|
lazy: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: () => false
|
default: () => false,
|
||||||
},
|
},
|
||||||
visible: {
|
visible: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: () => false
|
default: () => false,
|
||||||
},
|
},
|
||||||
disabled: {
|
disabled: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: () => false
|
default: () => false,
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "ITooltip",
|
name: 'ITooltip',
|
||||||
props: tooltipProps,
|
props: tooltipProps,
|
||||||
emits: ["change", "update:visible"],
|
emits: ['change', 'update:visible'],
|
||||||
setup(props, { slots, emit }) {
|
setup(props, { slots, emit }) {
|
||||||
const isOpen = ref(props.visible)
|
const isOpen = ref(props.visible)
|
||||||
|
|
||||||
syncRefs(useVModel(props, "visible"), isOpen)
|
syncRefs(useVModel(props, 'visible'), isOpen)
|
||||||
|
|
||||||
provideShow(isOpen)
|
provideShow(isOpen)
|
||||||
|
|
||||||
@@ -47,13 +57,19 @@ export default defineComponent({
|
|||||||
|
|
||||||
const dropdownPosition = reactive({ x: 0, y: 0 })
|
const dropdownPosition = reactive({ x: 0, y: 0 })
|
||||||
|
|
||||||
const isShow = computed(() => isOpen.value && triggerRef.value && popupRef.value && dropdownPosition.x + dropdownPosition.y > 0)
|
const isShow = computed(
|
||||||
|
() =>
|
||||||
|
isOpen.value &&
|
||||||
|
triggerRef.value &&
|
||||||
|
popupRef.value &&
|
||||||
|
dropdownPosition.x + dropdownPosition.y > 0,
|
||||||
|
)
|
||||||
|
|
||||||
const dropdownStyle = computed<CSSProperties>(() => {
|
const dropdownStyle = computed<CSSProperties>(() => {
|
||||||
return {
|
return {
|
||||||
left: `${dropdownPosition.x}px`,
|
left: `${dropdownPosition.x}px`,
|
||||||
top: `${dropdownPosition.y}px`,
|
top: `${dropdownPosition.y}px`,
|
||||||
visibility: isShow.value ? "visible" : "hidden"
|
visibility: isShow.value ? 'visible' : 'hidden',
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -66,9 +82,9 @@ export default defineComponent({
|
|||||||
timer = setTimeout(
|
timer = setTimeout(
|
||||||
() => {
|
() => {
|
||||||
isOpen.value = true
|
isOpen.value = true
|
||||||
emit("change", true)
|
emit('change', true)
|
||||||
},
|
},
|
||||||
props.lazy ? 800 : 100
|
props.lazy ? 800 : 100,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,7 +94,7 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
clearTimeout(timer)
|
clearTimeout(timer)
|
||||||
isOpen.value = false
|
isOpen.value = false
|
||||||
emit("change", false)
|
emit('change', false)
|
||||||
}
|
}
|
||||||
|
|
||||||
function resize() {
|
function resize() {
|
||||||
@@ -96,34 +112,37 @@ export default defineComponent({
|
|||||||
const offset = props.offset
|
const offset = props.offset
|
||||||
|
|
||||||
switch (props.position) {
|
switch (props.position) {
|
||||||
case "auto":
|
case 'auto':
|
||||||
case "bottom":
|
case 'bottom':
|
||||||
x = left + width / 2
|
x = left + width / 2
|
||||||
y = top + height + offset
|
y = top + height + offset
|
||||||
break
|
break
|
||||||
case "top":
|
case 'top':
|
||||||
x = left
|
x = left
|
||||||
y = top - pHeight - offset
|
y = top - pHeight - offset
|
||||||
break
|
break
|
||||||
case "left":
|
case 'left':
|
||||||
x = left - pWidth - offset
|
x = left - pWidth - offset
|
||||||
y = top
|
y = top
|
||||||
break
|
break
|
||||||
case "right":
|
case 'right':
|
||||||
x = left + width + offset
|
x = left + width + offset
|
||||||
y = top
|
y = top
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if (props.position == "auto") {
|
if (props.position == 'auto') {
|
||||||
x = window.innerWidth - x > 500 ? x + 20 : x - 20 - 310
|
x = window.innerWidth - x > 500 ? x + 20 : x - 20 - 310
|
||||||
y = window.innerHeight - y > popup.offsetHeight + 50 ? y : window.innerHeight - (popup.offsetHeight + 50)
|
y =
|
||||||
|
window.innerHeight - y > popup.offsetHeight + 50
|
||||||
|
? y
|
||||||
|
: window.innerHeight - (popup.offsetHeight + 50)
|
||||||
}
|
}
|
||||||
dropdownPosition.x = x
|
dropdownPosition.x = x
|
||||||
dropdownPosition.y = y
|
dropdownPosition.y = y
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(isOpen, val => {
|
watch(isOpen, (val) => {
|
||||||
if (val) {
|
if (val) {
|
||||||
mounted.value = true
|
mounted.value = true
|
||||||
}
|
}
|
||||||
@@ -133,12 +152,16 @@ export default defineComponent({
|
|||||||
return () => {
|
return () => {
|
||||||
return (
|
return (
|
||||||
<div {...{ onMouseout, onMouseover }} ref={triggerRef}>
|
<div {...{ onMouseout, onMouseover }} ref={triggerRef}>
|
||||||
{renderSlot(slots, "default")}
|
{renderSlot(slots, 'default')}
|
||||||
<Teleport to="body">
|
<Teleport to="body">
|
||||||
<Transition name="dropdown" mode="out-in">
|
<Transition name="dropdown" mode="out-in">
|
||||||
{mounted.value && !props.disabled && (
|
{mounted.value && !props.disabled && (
|
||||||
<div class={["i-popper z-999", props.popClass]} style={dropdownStyle.value} ref={popupRef}>
|
<div
|
||||||
{renderSlot(slots, "popper")}
|
class={['i-popper z-999', props.popClass]}
|
||||||
|
style={dropdownStyle.value}
|
||||||
|
ref={popupRef}
|
||||||
|
>
|
||||||
|
{renderSlot(slots, 'popper')}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</Transition>
|
</Transition>
|
||||||
@@ -146,5 +169,5 @@ export default defineComponent({
|
|||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,101 +1,101 @@
|
|||||||
<script lang="tsx">
|
<script lang="tsx">
|
||||||
import { onKeyStroke, syncRef, useVModel } from "@vueuse/core"
|
import { onKeyStroke, syncRef, useVModel } from '@vueuse/core'
|
||||||
import type { PropType, RendererElement } from "vue"
|
import type { PropType, RendererElement } from 'vue'
|
||||||
import { defineComponent, ref, renderSlot } from "vue"
|
import { defineComponent, ref, renderSlot } from 'vue'
|
||||||
|
|
||||||
import CalcDialog from "@/components/calc/dialog/index.vue"
|
import CalcDialog from '@/components/calc/dialog/index.vue'
|
||||||
import CalcButton from "@/components/calc/button/index.vue"
|
import CalcButton from '@/components/calc/button/index.vue'
|
||||||
import type { JSX } from "vue/jsx-runtime"
|
import type { JSX } from 'vue/jsx-runtime'
|
||||||
|
|
||||||
export type ActionDialogResult = "ok" | "reject" | "cancel" | "none"
|
export type ActionDialogResult = 'ok' | 'reject' | 'cancel' | 'none'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "IActionDialog",
|
name: 'IActionDialog',
|
||||||
props: {
|
props: {
|
||||||
visible: {
|
visible: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: () => false
|
default: () => false,
|
||||||
},
|
},
|
||||||
class: {
|
class: {
|
||||||
type: String
|
type: String,
|
||||||
},
|
},
|
||||||
mask: {
|
mask: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: () => false
|
default: () => false,
|
||||||
},
|
},
|
||||||
// 模态框
|
// 模态框
|
||||||
modal: {
|
modal: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: () => false
|
default: () => false,
|
||||||
},
|
},
|
||||||
header: {
|
header: {
|
||||||
type: [String, Boolean] as PropType<string | boolean>,
|
type: [String, Boolean] as PropType<string | boolean>,
|
||||||
default: () => true
|
default: () => true,
|
||||||
},
|
},
|
||||||
drag: {
|
drag: {
|
||||||
type: String as PropType<"header" | "all" | "none">,
|
type: String as PropType<'header' | 'all' | 'none'>,
|
||||||
default: () => "header"
|
default: () => 'header',
|
||||||
},
|
},
|
||||||
okButton: {
|
okButton: {
|
||||||
type: [String, Boolean],
|
type: [String, Boolean],
|
||||||
default: "确定"
|
default: '确定',
|
||||||
},
|
},
|
||||||
rejectButton: {
|
rejectButton: {
|
||||||
type: [String, Boolean],
|
type: [String, Boolean],
|
||||||
default: false
|
default: false,
|
||||||
},
|
},
|
||||||
cancelButton: {
|
cancelButton: {
|
||||||
type: [String, Boolean],
|
type: [String, Boolean],
|
||||||
default: "取消"
|
default: '取消',
|
||||||
},
|
},
|
||||||
closeOnYes: {
|
closeOnYes: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: () => true
|
default: () => true,
|
||||||
},
|
},
|
||||||
closeOnCancel: {
|
closeOnCancel: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: () => true
|
default: () => true,
|
||||||
},
|
},
|
||||||
closeOnReject: {
|
closeOnReject: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: () => true
|
default: () => true,
|
||||||
},
|
},
|
||||||
closeOnEsc: {
|
closeOnEsc: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: () => true
|
default: () => true,
|
||||||
},
|
},
|
||||||
cache: {
|
cache: {
|
||||||
// 维持窗口状态
|
// 维持窗口状态
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: () => true
|
default: () => true,
|
||||||
},
|
},
|
||||||
defaultStatus: {
|
defaultStatus: {
|
||||||
type: String as PropType<ActionDialogResult>,
|
type: String as PropType<ActionDialogResult>,
|
||||||
default: () => "cancel"
|
default: () => 'cancel',
|
||||||
},
|
},
|
||||||
appendTo: {
|
appendTo: {
|
||||||
type: [Object, String] as PropType<string | RendererElement | null | undefined>,
|
type: [Object, String] as PropType<string | RendererElement | null | undefined>,
|
||||||
default: "body"
|
default: 'body',
|
||||||
},
|
},
|
||||||
scale: {
|
scale: {
|
||||||
type: Number,
|
type: Number,
|
||||||
default: 1.0
|
default: 1.0,
|
||||||
}
|
|
||||||
},
|
},
|
||||||
emits: ["close", "ok", "cancel", "action", "update:visible"],
|
},
|
||||||
|
emits: ['close', 'ok', 'cancel', 'action', 'update:visible'],
|
||||||
setup(props, { emit, slots }) {
|
setup(props, { emit, slots }) {
|
||||||
const visible = ref(props.visible)
|
const visible = ref(props.visible)
|
||||||
|
|
||||||
syncRef(useVModel(props, "visible"), visible, { direction: "both" })
|
syncRef(useVModel(props, 'visible'), visible, { direction: 'both' })
|
||||||
|
|
||||||
const result = ref<ActionDialogResult>(props.defaultStatus)
|
const result = ref<ActionDialogResult>(props.defaultStatus)
|
||||||
|
|
||||||
function close() {
|
function close() {
|
||||||
visible.value = false
|
visible.value = false
|
||||||
emit("close", result.value)
|
emit('close', result.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
onKeyStroke("ESC", (e: Event) => {
|
onKeyStroke('ESC', (e: Event) => {
|
||||||
if (visible.value && props.closeOnEsc) {
|
if (visible.value && props.closeOnEsc) {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
close()
|
close()
|
||||||
@@ -103,21 +103,21 @@ export default defineComponent({
|
|||||||
})
|
})
|
||||||
|
|
||||||
function onOkClick() {
|
function onOkClick() {
|
||||||
result.value = "ok"
|
result.value = 'ok'
|
||||||
if (props.closeOnYes) {
|
if (props.closeOnYes) {
|
||||||
close()
|
close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function onRejectClick() {
|
function onRejectClick() {
|
||||||
result.value = "reject"
|
result.value = 'reject'
|
||||||
if (props.closeOnReject) {
|
if (props.closeOnReject) {
|
||||||
close()
|
close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function onCancelClick() {
|
function onCancelClick() {
|
||||||
result.value = "cancel"
|
result.value = 'cancel'
|
||||||
if (props.closeOnCancel) {
|
if (props.closeOnCancel) {
|
||||||
close()
|
close()
|
||||||
}
|
}
|
||||||
@@ -133,28 +133,28 @@ export default defineComponent({
|
|||||||
if (props.okButton) {
|
if (props.okButton) {
|
||||||
buttons.push(
|
buttons.push(
|
||||||
<CalcButton class="mx-2px" type="primary" onClick={onOkClick}>
|
<CalcButton class="mx-2px" type="primary" onClick={onOkClick}>
|
||||||
{props.okButton === true ? "确定" : props.okButton}
|
{props.okButton === true ? '确定' : props.okButton}
|
||||||
</CalcButton>
|
</CalcButton>,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (props.rejectButton) {
|
if (props.rejectButton) {
|
||||||
buttons.push(
|
buttons.push(
|
||||||
<CalcButton class="mx-2px" type="primary" onClick={onRejectClick}>
|
<CalcButton class="mx-2px" type="primary" onClick={onRejectClick}>
|
||||||
{props.rejectButton === true ? "拒绝" : props.rejectButton}
|
{props.rejectButton === true ? '拒绝' : props.rejectButton}
|
||||||
</CalcButton>
|
</CalcButton>,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (props.cancelButton) {
|
if (props.cancelButton) {
|
||||||
buttons.push(
|
buttons.push(
|
||||||
<CalcButton class="mx-2px" onClick={onCancelClick}>
|
<CalcButton class="mx-2px" onClick={onCancelClick}>
|
||||||
{props.cancelButton === true ? "取消" : props.cancelButton}
|
{props.cancelButton === true ? '取消' : props.cancelButton}
|
||||||
</CalcButton>
|
</CalcButton>,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return <div class="flex pb-2 items-center justify-center">{buttons}</div>
|
return <div class="flex pb-2 items-center justify-center">{buttons}</div>
|
||||||
}
|
}
|
||||||
return renderSlot(slots, "action")
|
return renderSlot(slots, 'action')
|
||||||
}
|
}
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
@@ -165,16 +165,16 @@ export default defineComponent({
|
|||||||
drag={props.drag}
|
drag={props.drag}
|
||||||
mask={props.mask}
|
mask={props.mask}
|
||||||
modal={props.modal}
|
modal={props.modal}
|
||||||
header={props.header == true ? "提示" : props.header}
|
header={props.header == true ? '提示' : props.header}
|
||||||
appendTo={props.appendTo}
|
appendTo={props.appendTo}
|
||||||
scale={props.scale}
|
scale={props.scale}
|
||||||
>
|
>
|
||||||
<div class={["flex items-center justify-center"]}> {renderSlot(slots, "default")}</div>
|
<div class={['flex items-center justify-center']}> {renderSlot(slots, 'default')}</div>
|
||||||
{renderAction()}
|
{renderAction()}
|
||||||
</CalcDialog>
|
</CalcDialog>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,16 @@
|
|||||||
<script lang="tsx">
|
<script lang="tsx">
|
||||||
import { debouncedWatch, onClickOutside, useVModel } from "@vueuse/core"
|
import { debouncedWatch, onClickOutside, useVModel } from '@vueuse/core'
|
||||||
import type { CSSProperties, PropType } from "vue";
|
import type { CSSProperties, PropType } from 'vue'
|
||||||
import { Teleport, Transition, computed, defineComponent, onDeactivated, ref, renderList, watch } from "vue"
|
import {
|
||||||
|
Teleport,
|
||||||
|
Transition,
|
||||||
|
computed,
|
||||||
|
defineComponent,
|
||||||
|
onDeactivated,
|
||||||
|
ref,
|
||||||
|
renderList,
|
||||||
|
watch,
|
||||||
|
} from 'vue'
|
||||||
|
|
||||||
type HandleChangeFunction = (value: string | number) => string[] | Promise<string[]>
|
type HandleChangeFunction = (value: string | number) => string[] | Promise<string[]>
|
||||||
|
|
||||||
@@ -9,23 +18,23 @@ export default defineComponent({
|
|||||||
props: {
|
props: {
|
||||||
modelValue: {
|
modelValue: {
|
||||||
type: [String, Number] as PropType<string | number>,
|
type: [String, Number] as PropType<string | number>,
|
||||||
default: () => ""
|
default: () => '',
|
||||||
},
|
},
|
||||||
placeholder: {
|
placeholder: {
|
||||||
type: String,
|
type: String,
|
||||||
default: ""
|
default: '',
|
||||||
},
|
},
|
||||||
handleChange: {
|
handleChange: {
|
||||||
type: Function as PropType<HandleChangeFunction>,
|
type: Function as PropType<HandleChangeFunction>,
|
||||||
default: () => () => []
|
default: () => () => [],
|
||||||
},
|
},
|
||||||
delay: {
|
delay: {
|
||||||
type: Number,
|
type: Number,
|
||||||
default: 300
|
default: 300,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
setup(props, { emit }) {
|
setup(props, { emit }) {
|
||||||
const modelValue = useVModel(props, "modelValue")
|
const modelValue = useVModel(props, 'modelValue')
|
||||||
|
|
||||||
const isOpen = ref(false)
|
const isOpen = ref(false)
|
||||||
const triggerRef = ref<HTMLElement>()
|
const triggerRef = ref<HTMLElement>()
|
||||||
@@ -39,7 +48,7 @@ export default defineComponent({
|
|||||||
return {
|
return {
|
||||||
left: `${dropdownPosition.value.x}px`,
|
left: `${dropdownPosition.value.x}px`,
|
||||||
top: `${dropdownPosition.value.y}px`,
|
top: `${dropdownPosition.value.y}px`,
|
||||||
width: `${dropdownPosition.value.w}px`
|
width: `${dropdownPosition.value.w}px`,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -49,19 +58,19 @@ export default defineComponent({
|
|||||||
dropdownPosition.value = {
|
dropdownPosition.value = {
|
||||||
w: width,
|
w: width,
|
||||||
x: left,
|
x: left,
|
||||||
y: top + height + 2
|
y: top + height + 2,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onClickOutside(triggerRef, () => (isOpen.value = false))
|
onClickOutside(triggerRef, () => (isOpen.value = false))
|
||||||
|
|
||||||
window.addEventListener("resize", onResize)
|
window.addEventListener('resize', onResize)
|
||||||
window.addEventListener("scroll", onResize)
|
window.addEventListener('scroll', onResize)
|
||||||
|
|
||||||
onDeactivated(() => {
|
onDeactivated(() => {
|
||||||
window.removeEventListener("resize", onResize)
|
window.removeEventListener('resize', onResize)
|
||||||
window.removeEventListener("scroll", onResize)
|
window.removeEventListener('scroll', onResize)
|
||||||
})
|
})
|
||||||
|
|
||||||
function selectItem(item: string) {
|
function selectItem(item: string) {
|
||||||
@@ -74,17 +83,21 @@ export default defineComponent({
|
|||||||
|
|
||||||
const droplist = ref<string[]>([])
|
const droplist = ref<string[]>([])
|
||||||
|
|
||||||
debouncedWatch(modelValue, async value => (droplist.value = await props.handleChange(value)), {
|
debouncedWatch(
|
||||||
debounce: delay
|
modelValue,
|
||||||
})
|
async (value) => (droplist.value = await props.handleChange(value)),
|
||||||
|
{
|
||||||
|
debounce: delay,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
function handleInput() {
|
function handleInput() {
|
||||||
isOpen.value = droplist.value.length > 0
|
isOpen.value = droplist.value.length > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleKeyPress(event: KeyboardEvent) {
|
function handleKeyPress(event: KeyboardEvent) {
|
||||||
if (event.code == "Enter") {
|
if (event.code == 'Enter') {
|
||||||
emit("enter", modelValue.value)
|
emit('enter', modelValue.value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,12 +105,24 @@ export default defineComponent({
|
|||||||
return (
|
return (
|
||||||
<div class="i-autocomplete">
|
<div class="i-autocomplete">
|
||||||
<div class="i-autocomplete-trigger" ref={triggerRef}>
|
<div class="i-autocomplete-trigger" ref={triggerRef}>
|
||||||
<input onKeypress={handleKeyPress} class="i-autocomplete-input" onFocus={handleInput} onInput={handleInput} type="text" v-model={modelValue.value} placeholder={props.placeholder} />
|
<input
|
||||||
|
onKeypress={handleKeyPress}
|
||||||
|
class="i-autocomplete-input"
|
||||||
|
onFocus={handleInput}
|
||||||
|
onInput={handleInput}
|
||||||
|
type="text"
|
||||||
|
v-model={modelValue.value}
|
||||||
|
placeholder={props.placeholder}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<Teleport to="body">
|
<Teleport to="body">
|
||||||
<Transition name="dropdown" mode="out-in">
|
<Transition name="dropdown" mode="out-in">
|
||||||
<div class="i-autocomplete-dropdown" style={dropdownStyle.value} v-show={isOpen.value}>
|
<div
|
||||||
{renderList(droplist.value, item => (
|
class="i-autocomplete-dropdown"
|
||||||
|
style={dropdownStyle.value}
|
||||||
|
v-show={isOpen.value}
|
||||||
|
>
|
||||||
|
{renderList(droplist.value, (item) => (
|
||||||
<div class="i-autocomplete-dropdown-item" onClick={selectItem(item)}>
|
<div class="i-autocomplete-dropdown-item" onClick={selectItem(item)}>
|
||||||
{item}
|
{item}
|
||||||
</div>
|
</div>
|
||||||
@@ -108,7 +133,7 @@ export default defineComponent({
|
|||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -151,7 +176,7 @@ export default defineComponent({
|
|||||||
color: gray;
|
color: gray;
|
||||||
|
|
||||||
.i-select-down-icon {
|
.i-select-down-icon {
|
||||||
background-image: url("./img/select_down_disabled.png");
|
background-image: url('./img/select_down_disabled.png');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,57 +1,61 @@
|
|||||||
<script lang="tsx">
|
<script lang="tsx">
|
||||||
import { defineComponent, renderSlot } from "vue"
|
import { defineComponent, renderSlot } from 'vue'
|
||||||
import { RouterLink } from "vue-router"
|
import { RouterLink } from 'vue-router'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "CalcButton",
|
name: 'CalcButton',
|
||||||
props: {
|
props: {
|
||||||
small: {
|
small: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false
|
default: false,
|
||||||
},
|
},
|
||||||
to: {
|
to: {
|
||||||
type: String,
|
type: String,
|
||||||
default: null
|
default: null,
|
||||||
},
|
},
|
||||||
class: {
|
class: {
|
||||||
type: [String],
|
type: [String],
|
||||||
default: ""
|
default: '',
|
||||||
},
|
},
|
||||||
icon: {
|
icon: {
|
||||||
type: String
|
type: String,
|
||||||
},
|
},
|
||||||
type: {
|
type: {
|
||||||
type: String,
|
type: String,
|
||||||
default: "primary"
|
default: 'primary',
|
||||||
},
|
},
|
||||||
disabled: {
|
disabled: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false
|
default: false,
|
||||||
}
|
|
||||||
},
|
},
|
||||||
emits: ["click"],
|
},
|
||||||
|
emits: ['click'],
|
||||||
setup(props, { slots, emit }) {
|
setup(props, { slots, emit }) {
|
||||||
return () => {
|
return () => {
|
||||||
const proerpties = {
|
const proerpties = {
|
||||||
to: props.to,
|
to: props.to,
|
||||||
class: {
|
class: {
|
||||||
[props.class]: !!props.class,
|
[props.class]: !!props.class,
|
||||||
"i-button cursor-pointer outline-none text-shadow": true,
|
'i-button cursor-pointer outline-none text-shadow': true,
|
||||||
"small": props.small,
|
small: props.small,
|
||||||
[`icon-${props.icon}`]: !!props.icon
|
[`icon-${props.icon}`]: !!props.icon,
|
||||||
},
|
},
|
||||||
onClick: (e: MouseEvent) => {
|
onClick: (e: MouseEvent) => {
|
||||||
if (props.to) {
|
if (props.to) {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
}
|
}
|
||||||
emit("click", e)
|
emit('click', e)
|
||||||
},
|
},
|
||||||
disabled: props.disabled
|
disabled: props.disabled,
|
||||||
}
|
|
||||||
const content = renderSlot(slots, "default")
|
|
||||||
return props.to ? <RouterLink {...proerpties}>{content}</RouterLink> : <button {...proerpties}>{content}</button>
|
|
||||||
}
|
}
|
||||||
|
const content = renderSlot(slots, 'default')
|
||||||
|
return props.to ? (
|
||||||
|
<RouterLink {...proerpties}>{content}</RouterLink>
|
||||||
|
) : (
|
||||||
|
<button {...proerpties}>{content}</button>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
},
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -71,7 +75,7 @@ export default defineComponent({
|
|||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
transition: all 200ms ease-in-out;
|
transition: all 200ms ease-in-out;
|
||||||
|
|
||||||
&[class*="icon-"] {
|
&[class*='icon-'] {
|
||||||
min-width: 1px;
|
min-width: 1px;
|
||||||
width: 28px;
|
width: 28px;
|
||||||
height: 28px;
|
height: 28px;
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<script lang="tsx">
|
<script lang="tsx">
|
||||||
import { selectionEmits, selectionProps } from "hoci"
|
import { selectionEmits, selectionProps } from 'hoci'
|
||||||
import type { CSSProperties, PropType } from "vue";
|
import type { CSSProperties, PropType } from 'vue'
|
||||||
import { Teleport, Transition, computed, defineComponent, onDeactivated, ref, watch } from "vue"
|
import { Teleport, Transition, computed, defineComponent, onDeactivated, ref, watch } from 'vue'
|
||||||
|
|
||||||
import { onClickOutside, useVModel } from "@vueuse/core"
|
import { onClickOutside, useVModel } from '@vueuse/core'
|
||||||
interface ICascaderItem {
|
interface ICascaderItem {
|
||||||
label: string
|
label: string
|
||||||
id?: string | number
|
id?: string | number
|
||||||
@@ -13,33 +13,33 @@ interface ICascaderItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "ICascader",
|
name: 'ICascader',
|
||||||
props: {
|
props: {
|
||||||
...selectionProps,
|
...selectionProps,
|
||||||
disabled: {
|
disabled: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false
|
default: false,
|
||||||
},
|
},
|
||||||
width: {
|
width: {
|
||||||
type: Number,
|
type: Number,
|
||||||
default: 120
|
default: 120,
|
||||||
},
|
},
|
||||||
emptyLabel: {
|
emptyLabel: {
|
||||||
type: String
|
type: String,
|
||||||
},
|
},
|
||||||
highlight: {
|
highlight: {
|
||||||
type: String,
|
type: String,
|
||||||
// warn remind
|
// warn remind
|
||||||
default: ""
|
default: '',
|
||||||
},
|
},
|
||||||
items: {
|
items: {
|
||||||
type: Array as PropType<ICascaderItem[]>,
|
type: Array as PropType<ICascaderItem[]>,
|
||||||
default: () => []
|
default: () => [],
|
||||||
}
|
|
||||||
},
|
},
|
||||||
emits: [...selectionEmits, "select"],
|
},
|
||||||
|
emits: [...selectionEmits, 'select'],
|
||||||
setup(props, { emit }) {
|
setup(props, { emit }) {
|
||||||
const modelValue = useVModel(props, "modelValue")
|
const modelValue = useVModel(props, 'modelValue')
|
||||||
|
|
||||||
const isOpen = ref(false)
|
const isOpen = ref(false)
|
||||||
const triggerRef = ref<HTMLElement>()
|
const triggerRef = ref<HTMLElement>()
|
||||||
@@ -60,13 +60,13 @@ export default defineComponent({
|
|||||||
return {
|
return {
|
||||||
left: `${dropdownPosition.value.x}px`,
|
left: `${dropdownPosition.value.x}px`,
|
||||||
top: `${dropdownPosition.value.y}px`,
|
top: `${dropdownPosition.value.y}px`,
|
||||||
width: `${dropdownPosition.value.w}px`
|
width: `${dropdownPosition.value.w}px`,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return {
|
return {
|
||||||
left: `${dropdownPosition.value.x}px`,
|
left: `${dropdownPosition.value.x}px`,
|
||||||
bottom: `${dropdownPosition.value.z}px`,
|
bottom: `${dropdownPosition.value.z}px`,
|
||||||
width: `${dropdownPosition.value.w}px`
|
width: `${dropdownPosition.value.w}px`,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -79,26 +79,25 @@ export default defineComponent({
|
|||||||
w: width,
|
w: width,
|
||||||
x: left,
|
x: left,
|
||||||
y: top + height + 2,
|
y: top + height + 2,
|
||||||
z: 0
|
z: 0,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
dropdownPosition.value = {
|
dropdownPosition.value = {
|
||||||
w: width,
|
w: width,
|
||||||
x: left,
|
x: left,
|
||||||
z: window.innerHeight - top + 2,
|
z: window.innerHeight - top + 2,
|
||||||
y: 0
|
y: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
window.addEventListener('resize', onResize)
|
||||||
window.addEventListener("resize", onResize)
|
window.addEventListener('scroll', onResize)
|
||||||
window.addEventListener("scroll", onResize)
|
|
||||||
|
|
||||||
onDeactivated(() => {
|
onDeactivated(() => {
|
||||||
window.removeEventListener("resize", onResize)
|
window.removeEventListener('resize', onResize)
|
||||||
window.removeEventListener("scroll", onResize)
|
window.removeEventListener('scroll', onResize)
|
||||||
})
|
})
|
||||||
|
|
||||||
const selectItem = ref<ICascaderItem>()
|
const selectItem = ref<ICascaderItem>()
|
||||||
@@ -108,7 +107,7 @@ export default defineComponent({
|
|||||||
isOpen.value = false
|
isOpen.value = false
|
||||||
}
|
}
|
||||||
selectItem.value = item
|
selectItem.value = item
|
||||||
emit("select", item.value)
|
emit('select', item.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadNode(item: ICascaderItem) {
|
function loadNode(item: ICascaderItem) {
|
||||||
@@ -122,11 +121,15 @@ export default defineComponent({
|
|||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
return (
|
return (
|
||||||
<div class={["min-w-20 w-40 i-cascader"].concat(props.highlight)} onClick={collapse} ref={selectRef}>
|
<div
|
||||||
|
class={['min-w-20 w-40 i-cascader'].concat(props.highlight)}
|
||||||
|
onClick={collapse}
|
||||||
|
ref={selectRef}
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
class={{
|
class={{
|
||||||
"i-cascader-trigger": true,
|
'i-cascader-trigger': true,
|
||||||
"disabled": props.disabled
|
disabled: props.disabled,
|
||||||
}}
|
}}
|
||||||
ref={triggerRef}
|
ref={triggerRef}
|
||||||
>
|
>
|
||||||
@@ -151,7 +154,7 @@ export default defineComponent({
|
|||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -194,7 +197,7 @@ $text-color: #937639;
|
|||||||
}
|
}
|
||||||
|
|
||||||
.i-cascader-down-icon {
|
.i-cascader-down-icon {
|
||||||
background-image: url("./img/select_down.png");
|
background-image: url('./img/select_down.png');
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-position: center;
|
background-position: center;
|
||||||
@@ -204,7 +207,7 @@ $text-color: #937639;
|
|||||||
}
|
}
|
||||||
|
|
||||||
.i-cascader-down-icon:active {
|
.i-cascader-down-icon:active {
|
||||||
background-image: url("./img/select_down_clicked.png");
|
background-image: url('./img/select_down_clicked.png');
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-position: center;
|
background-position: center;
|
||||||
@@ -217,7 +220,7 @@ $text-color: #937639;
|
|||||||
color: gray;
|
color: gray;
|
||||||
|
|
||||||
.i-cascader-down-icon {
|
.i-cascader-down-icon {
|
||||||
background-image: url("./img/select_down_disabled.png");
|
background-image: url('./img/select_down_disabled.png');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,25 +1,25 @@
|
|||||||
<script lang="tsx">
|
<script lang="tsx">
|
||||||
import { defineComponent, provide } from "vue"
|
import { defineComponent, provide } from 'vue'
|
||||||
import { selectionEmits, selectionProps, useSelectionList } from "hoci"
|
import { selectionEmits, selectionProps, useSelectionList } from 'hoci'
|
||||||
import { CHECKBOX_GROUP } from "../shared"
|
import { CHECKBOX_GROUP } from '../shared'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "ICheckboxGroup",
|
name: 'ICheckboxGroup',
|
||||||
components: {},
|
components: {},
|
||||||
props: {
|
props: {
|
||||||
...selectionProps,
|
...selectionProps,
|
||||||
activeClass: {
|
activeClass: {
|
||||||
type: String,
|
type: String,
|
||||||
default: "checked"
|
default: 'checked',
|
||||||
},
|
},
|
||||||
unactiveClass: {
|
unactiveClass: {
|
||||||
type: String,
|
type: String,
|
||||||
default: "unchecked"
|
default: 'unchecked',
|
||||||
},
|
},
|
||||||
multiple: {
|
multiple: {
|
||||||
type: [Boolean, Number],
|
type: [Boolean, Number],
|
||||||
default: true
|
default: true,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
emits: [...selectionEmits],
|
emits: [...selectionEmits],
|
||||||
|
|
||||||
@@ -29,7 +29,7 @@ export default defineComponent({
|
|||||||
const { render } = useSelectionList(props, context)
|
const { render } = useSelectionList(props, context)
|
||||||
|
|
||||||
return () => render()
|
return () => render()
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -39,7 +39,7 @@ export default defineComponent({
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
&.checked {
|
&.checked {
|
||||||
.i-checkbox-icon {
|
.i-checkbox-icon {
|
||||||
background-image: url("@/assets/img/control/checkbox_checked.png");
|
background-image: url('@/assets/img/control/checkbox_checked.png');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,7 +48,7 @@ export default defineComponent({
|
|||||||
min-width: 12px;
|
min-width: 12px;
|
||||||
height: 12px;
|
height: 12px;
|
||||||
margin-right: 4px;
|
margin-right: 4px;
|
||||||
background-image: url("@/assets/img/control/checkbox_uncheck.png");
|
background-image: url('@/assets/img/control/checkbox_uncheck.png');
|
||||||
}
|
}
|
||||||
|
|
||||||
.i-checkbox-icon-disable {
|
.i-checkbox-icon-disable {
|
||||||
@@ -56,12 +56,12 @@ export default defineComponent({
|
|||||||
min-width: 12px;
|
min-width: 12px;
|
||||||
height: 12px;
|
height: 12px;
|
||||||
margin-right: 4px;
|
margin-right: 4px;
|
||||||
background-image: url("@/assets/img/control/checkbox_disable.png");
|
background-image: url('@/assets/img/control/checkbox_disable.png');
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover:not(.checked) {
|
&:hover:not(.checked) {
|
||||||
.i-checkbox-icon {
|
.i-checkbox-icon {
|
||||||
background-image: url("@/assets/img/control/checkbox_hover.png");
|
background-image: url('@/assets/img/control/checkbox_hover.png');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,33 +1,41 @@
|
|||||||
<script lang="tsx">
|
<script lang="tsx">
|
||||||
import { useToggle, useVModel } from "@vueuse/core"
|
import { useToggle, useVModel } from '@vueuse/core'
|
||||||
import { defineComponent, renderSlot } from "vue"
|
import { defineComponent, renderSlot } from 'vue'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "ICollapse",
|
name: 'ICollapse',
|
||||||
props: {
|
props: {
|
||||||
title: {
|
title: {
|
||||||
type: String
|
type: String,
|
||||||
},
|
},
|
||||||
modelValue: {
|
modelValue: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: () => true
|
default: () => true,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
setup(props, { slots, emit }) {
|
setup(props, { slots, emit }) {
|
||||||
const modelValue = useVModel(props, "modelValue", emit, { passive: true })
|
const modelValue = useVModel(props, 'modelValue', emit, { passive: true })
|
||||||
|
|
||||||
const toggle = useToggle(modelValue)
|
const toggle = useToggle(modelValue)
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
return (
|
return (
|
||||||
<div class="rounded h-auto bg-hex-00000078 border-1 border-hex-ffffff28 my-1 overflow-hidden">
|
<div class="rounded h-auto bg-hex-00000078 border-1 border-hex-ffffff28 my-1 overflow-hidden">
|
||||||
<div onClick={() => toggle()} v-text={props.title} class="bg-gradient-to-b flex from-hex-244281 to-hex-122438 h-6 text-xs text-center w-full items-center justify-center"></div>
|
<div
|
||||||
<div class={["transition-all", "ease-out-in", "h-auto"].concat(modelValue.value ? ["max-h-200"] : ["max-h-0"])}>
|
onClick={() => toggle()}
|
||||||
<div class="p-2">{renderSlot(slots, "default")}</div>
|
v-text={props.title}
|
||||||
|
class="bg-gradient-to-b flex from-hex-244281 to-hex-122438 h-6 text-xs text-center w-full items-center justify-center"
|
||||||
|
></div>
|
||||||
|
<div
|
||||||
|
class={['transition-all', 'ease-out-in', 'h-auto'].concat(
|
||||||
|
modelValue.value ? ['max-h-200'] : ['max-h-0'],
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<div class="p-2">{renderSlot(slots, 'default')}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,63 +1,72 @@
|
|||||||
<script lang="tsx">
|
<script lang="tsx">
|
||||||
import { onClickOutside, onKeyDown, syncRef, useDraggable, useVModel } from "@vueuse/core"
|
import { onClickOutside, onKeyDown, syncRef, useDraggable, useVModel } from '@vueuse/core'
|
||||||
import type { PropType, RendererElement } from "vue"
|
import type { PropType, RendererElement } from 'vue'
|
||||||
import { Teleport, Transition, computed, defineComponent, provide, ref, renderSlot, watch } from "vue"
|
import {
|
||||||
import { provideShow } from "@/components/hooks/show"
|
Teleport,
|
||||||
|
Transition,
|
||||||
|
computed,
|
||||||
|
defineComponent,
|
||||||
|
provide,
|
||||||
|
ref,
|
||||||
|
renderSlot,
|
||||||
|
watch,
|
||||||
|
} from 'vue'
|
||||||
|
import { provideShow } from '@/components/hooks/show'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "IDialog",
|
name: 'IDialog',
|
||||||
props: {
|
props: {
|
||||||
visible: {
|
visible: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: () => false
|
default: () => false,
|
||||||
},
|
},
|
||||||
class: {
|
class: {
|
||||||
type: String
|
type: String,
|
||||||
},
|
},
|
||||||
mask: {
|
mask: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: () => false
|
default: () => false,
|
||||||
},
|
},
|
||||||
// 模态框
|
// 模态框
|
||||||
modal: {
|
modal: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: () => false
|
default: () => false,
|
||||||
},
|
},
|
||||||
header: {
|
header: {
|
||||||
type: [String, Boolean],
|
type: [String, Boolean],
|
||||||
default: () => "提示"
|
default: () => '提示',
|
||||||
},
|
},
|
||||||
closeOnEsc: {
|
closeOnEsc: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: () => true
|
default: () => true,
|
||||||
},
|
},
|
||||||
closeButton: {
|
closeButton: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: () => true
|
default: () => true,
|
||||||
},
|
},
|
||||||
cache: {
|
cache: {
|
||||||
// 维持窗口状态
|
// 维持窗口状态
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: () => true
|
default: () => true,
|
||||||
},
|
},
|
||||||
lazy: {
|
lazy: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: () => false
|
default: () => false,
|
||||||
},
|
},
|
||||||
drag: {
|
drag: {
|
||||||
type: String as PropType<"header" | "all" | "none">,
|
type: String as PropType<'header' | 'all' | 'none'>,
|
||||||
default: () => "header"
|
default: () => 'header',
|
||||||
},
|
},
|
||||||
appendTo: {
|
appendTo: {
|
||||||
type: [Object, String] as PropType<string | RendererElement | null | undefined>,
|
type: [Object, String] as PropType<string | RendererElement | null | undefined>,
|
||||||
default: "body"
|
default: 'body',
|
||||||
},
|
},
|
||||||
scale: {
|
scale: {
|
||||||
type: Number,
|
type: Number,
|
||||||
default: 1
|
default: 1,
|
||||||
}
|
|
||||||
},
|
},
|
||||||
emits: ["close", "update:visible"],
|
},
|
||||||
|
emits: ['close', 'update:visible'],
|
||||||
setup(props, { emit, slots }) {
|
setup(props, { emit, slots }) {
|
||||||
const dialogRef = ref<HTMLElement | null>(null)
|
const dialogRef = ref<HTMLElement | null>(null)
|
||||||
const headerRef = ref<HTMLElement | null>(null)
|
const headerRef = ref<HTMLElement | null>(null)
|
||||||
@@ -66,18 +75,18 @@ export default defineComponent({
|
|||||||
|
|
||||||
provideShow(visible)
|
provideShow(visible)
|
||||||
|
|
||||||
provide("dialogRef", dialogRef)
|
provide('dialogRef', dialogRef)
|
||||||
|
|
||||||
const loaded = ref(!props.lazy)
|
const loaded = ref(!props.lazy)
|
||||||
|
|
||||||
const stopLoadWatch = watch(visible, val => {
|
const stopLoadWatch = watch(visible, (val) => {
|
||||||
if (val) {
|
if (val) {
|
||||||
loaded.value = true
|
loaded.value = true
|
||||||
stopLoadWatch()
|
stopLoadWatch()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
syncRef(useVModel(props, "visible"), visible, { direction: "both" })
|
syncRef(useVModel(props, 'visible'), visible, { direction: 'both' })
|
||||||
|
|
||||||
onClickOutside(dialogRef, () => {
|
onClickOutside(dialogRef, () => {
|
||||||
if (props.modal) {
|
if (props.modal) {
|
||||||
@@ -87,17 +96,17 @@ export default defineComponent({
|
|||||||
|
|
||||||
function close() {
|
function close() {
|
||||||
visible.value = false
|
visible.value = false
|
||||||
emit("close")
|
emit('close')
|
||||||
}
|
}
|
||||||
|
|
||||||
onKeyDown(
|
onKeyDown(
|
||||||
"Escape",
|
'Escape',
|
||||||
() => {
|
() => {
|
||||||
if (visible.value && props.closeOnEsc) {
|
if (visible.value && props.closeOnEsc) {
|
||||||
close()
|
close()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ target: document }
|
{ target: document },
|
||||||
)
|
)
|
||||||
|
|
||||||
const init = ref(true)
|
const init = ref(true)
|
||||||
@@ -105,24 +114,24 @@ export default defineComponent({
|
|||||||
const { x, y, style } = useDraggable(
|
const { x, y, style } = useDraggable(
|
||||||
computed(() => {
|
computed(() => {
|
||||||
switch (props.drag) {
|
switch (props.drag) {
|
||||||
case "header":
|
case 'header':
|
||||||
return headerRef.value
|
return headerRef.value
|
||||||
case "all":
|
case 'all':
|
||||||
return dialogRef.value
|
return dialogRef.value
|
||||||
case "none":
|
case 'none':
|
||||||
default:
|
default:
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
initialValue: { x: 0, y: 0 }
|
initialValue: { x: 0, y: 0 },
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
const isFixed = computed(() => x.value + y.value > 0)
|
const isFixed = computed(() => x.value + y.value > 0)
|
||||||
|
|
||||||
const appendToRef = computed(() => {
|
const appendToRef = computed(() => {
|
||||||
return props.appendTo || "body"
|
return props.appendTo || 'body'
|
||||||
})
|
})
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
@@ -130,19 +139,41 @@ export default defineComponent({
|
|||||||
<Teleport to={appendToRef.value}>
|
<Teleport to={appendToRef.value}>
|
||||||
<Transition name="dialog" mode="out-in">
|
<Transition name="dialog" mode="out-in">
|
||||||
{loaded.value && (props.cache || visible.value) && (
|
{loaded.value && (props.cache || visible.value) && (
|
||||||
<div v-show={visible.value} class={["dialog-mask w-full h-full fixed top-0 left-0 z-999 flex justify-center items-center "].concat(props.mask ? "bg-hex-000 bg-opacity-66" : "")} style={`transform: scale(${props.scale});${x.value == 0 && y.value == 0 ?"transform-origin:center":"transform-origin:left top"}`}>
|
<div
|
||||||
<div ref={dialogRef} class={["h-auto border-1 border-hex-2b2b2b border-solid shadow-sm round-1 dialog min-w-48", isFixed.value ? "fixed" : "", props.class]} style={`top:${y.value/props.scale}px;left:${x.value/props.scale}px`}>
|
v-show={visible.value}
|
||||||
|
class={[
|
||||||
|
'dialog-mask w-full h-full fixed top-0 left-0 z-999 flex justify-center items-center ',
|
||||||
|
].concat(props.mask ? 'bg-hex-000 bg-opacity-66' : '')}
|
||||||
|
style={`transform: scale(${props.scale});${x.value == 0 && y.value == 0 ? 'transform-origin:center' : 'transform-origin:left top'}`}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
ref={dialogRef}
|
||||||
|
class={[
|
||||||
|
'h-auto border-1 border-hex-2b2b2b border-solid shadow-sm round-1 dialog min-w-48',
|
||||||
|
isFixed.value ? 'fixed' : '',
|
||||||
|
props.class,
|
||||||
|
]}
|
||||||
|
style={`top:${y.value / props.scale}px;left:${x.value / props.scale}px`}
|
||||||
|
>
|
||||||
{props.header && (
|
{props.header && (
|
||||||
<div ref={headerRef} class="flex h-4 px-1 leading-4 z-9999 justify-center relative app-header py-2px">
|
<div
|
||||||
|
ref={headerRef}
|
||||||
|
class="flex h-4 px-1 leading-4 z-9999 justify-center relative app-header py-2px"
|
||||||
|
>
|
||||||
<div class="text-xs text-shadow ">{props.header}</div>
|
<div class="text-xs text-shadow ">{props.header}</div>
|
||||||
{props.closeButton && (
|
{props.closeButton && (
|
||||||
<div class="flex top-0 right-0 bottom-0 items-center absolute">
|
<div class="flex top-0 right-0 bottom-0 items-center absolute">
|
||||||
<div onClick={close} class="cursor-pointer flex h-4 text-center w-4 items-center close-icon"></div>
|
<div
|
||||||
|
onClick={close}
|
||||||
|
class="cursor-pointer flex h-4 text-center w-4 items-center close-icon"
|
||||||
|
></div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div class="bg-hex-000 bg-opacity-80 text-white text-xs">{renderSlot(slots, "default")}</div>
|
<div class="bg-hex-000 bg-opacity-80 text-white text-xs">
|
||||||
|
{renderSlot(slots, 'default')}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@@ -150,7 +181,7 @@ export default defineComponent({
|
|||||||
</Teleport>
|
</Teleport>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -1,33 +1,42 @@
|
|||||||
<script lang="tsx">
|
<script lang="tsx">
|
||||||
import { selectionEmits, selectionProps, useSelectionList } from "hoci"
|
import { selectionEmits, selectionProps, useSelectionList } from 'hoci'
|
||||||
import type { CSSProperties, PropType, RendererElement } from "vue";
|
import type { CSSProperties, PropType, RendererElement } from 'vue'
|
||||||
import { Teleport, Transition, computed, defineComponent, onDeactivated, ref, renderSlot, watch } from "vue"
|
import {
|
||||||
|
Teleport,
|
||||||
|
Transition,
|
||||||
|
computed,
|
||||||
|
defineComponent,
|
||||||
|
onDeactivated,
|
||||||
|
ref,
|
||||||
|
renderSlot,
|
||||||
|
watch,
|
||||||
|
} from 'vue'
|
||||||
|
|
||||||
import { onClickOutside } from "@vueuse/core"
|
import { onClickOutside } from '@vueuse/core'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "IIconselect",
|
name: 'IIconselect',
|
||||||
props: {
|
props: {
|
||||||
...selectionProps,
|
...selectionProps,
|
||||||
disabled: {
|
disabled: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false
|
default: false,
|
||||||
},
|
},
|
||||||
width: {
|
width: {
|
||||||
type: Number,
|
type: Number,
|
||||||
default: 28
|
default: 28,
|
||||||
},
|
},
|
||||||
emptyLabel: {
|
emptyLabel: {
|
||||||
type: String
|
type: String,
|
||||||
},
|
},
|
||||||
columnNum: {
|
columnNum: {
|
||||||
type: Number,
|
type: Number,
|
||||||
default: 1
|
default: 1,
|
||||||
},
|
},
|
||||||
appendTo: {
|
appendTo: {
|
||||||
type: [Object, String] as PropType<string | RendererElement | null | undefined>,
|
type: [Object, String] as PropType<string | RendererElement | null | undefined>,
|
||||||
default: "body"
|
default: 'body',
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
emits: selectionEmits,
|
emits: selectionEmits,
|
||||||
setup(props, context) {
|
setup(props, context) {
|
||||||
@@ -36,9 +45,9 @@ export default defineComponent({
|
|||||||
const { renderItem } = useSelectionList(() => {
|
const { renderItem } = useSelectionList(() => {
|
||||||
return {
|
return {
|
||||||
...props,
|
...props,
|
||||||
itemClass: "i-option",
|
itemClass: 'i-option',
|
||||||
activeClass: "active",
|
activeClass: 'active',
|
||||||
unactiveClass: "unactive"
|
unactiveClass: 'unactive',
|
||||||
}
|
}
|
||||||
}, context)
|
}, context)
|
||||||
|
|
||||||
@@ -52,7 +61,7 @@ export default defineComponent({
|
|||||||
watch(isOpen, onResize)
|
watch(isOpen, onResize)
|
||||||
|
|
||||||
const appendToRef = computed(() => {
|
const appendToRef = computed(() => {
|
||||||
return props.appendTo || "body"
|
return props.appendTo || 'body'
|
||||||
})
|
})
|
||||||
|
|
||||||
function collapse() {
|
function collapse() {
|
||||||
@@ -66,7 +75,7 @@ export default defineComponent({
|
|||||||
return {
|
return {
|
||||||
left: `${dropdownPosition.value.x}px`,
|
left: `${dropdownPosition.value.x}px`,
|
||||||
top: `${dropdownPosition.value.y}px`,
|
top: `${dropdownPosition.value.y}px`,
|
||||||
width: `${columnNum.value * 32 + 11}px`
|
width: `${columnNum.value * 32 + 11}px`,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -76,19 +85,19 @@ export default defineComponent({
|
|||||||
dropdownPosition.value = {
|
dropdownPosition.value = {
|
||||||
w: width,
|
w: width,
|
||||||
x: left - 2,
|
x: left - 2,
|
||||||
y: top + height + 2
|
y: top + height + 2,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onClickOutside(triggerRef, () => (isOpen.value = false))
|
onClickOutside(triggerRef, () => (isOpen.value = false))
|
||||||
|
|
||||||
window.addEventListener("resize", onResize)
|
window.addEventListener('resize', onResize)
|
||||||
window.addEventListener("scroll", onResize)
|
window.addEventListener('scroll', onResize)
|
||||||
|
|
||||||
onDeactivated(() => {
|
onDeactivated(() => {
|
||||||
window.removeEventListener("resize", onResize)
|
window.removeEventListener('resize', onResize)
|
||||||
window.removeEventListener("scroll", onResize)
|
window.removeEventListener('scroll', onResize)
|
||||||
})
|
})
|
||||||
|
|
||||||
const { slots } = context
|
const { slots } = context
|
||||||
@@ -101,8 +110,8 @@ export default defineComponent({
|
|||||||
<div class="i-icon-select" onClick={collapse}>
|
<div class="i-icon-select" onClick={collapse}>
|
||||||
<div
|
<div
|
||||||
class={{
|
class={{
|
||||||
"i-select-trigger": true,
|
'i-select-trigger': true,
|
||||||
"disabled": props.disabled
|
disabled: props.disabled,
|
||||||
}}
|
}}
|
||||||
ref={triggerRef}
|
ref={triggerRef}
|
||||||
>
|
>
|
||||||
@@ -111,14 +120,14 @@ export default defineComponent({
|
|||||||
<Teleport to={appendToRef.value}>
|
<Teleport to={appendToRef.value}>
|
||||||
<Transition name="dropdown" mode="out-in">
|
<Transition name="dropdown" mode="out-in">
|
||||||
<div class="i-icon-select-dropdown" style={dropdownStyle.value} v-show={isOpen.value}>
|
<div class="i-icon-select-dropdown" style={dropdownStyle.value} v-show={isOpen.value}>
|
||||||
{renderSlot(slots, "default")}
|
{renderSlot(slots, 'default')}
|
||||||
</div>
|
</div>
|
||||||
</Transition>
|
</Transition>
|
||||||
</Teleport>
|
</Teleport>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -194,11 +203,11 @@ export default defineComponent({
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
&.active::before {
|
&.active::before {
|
||||||
content: "";
|
content: '';
|
||||||
width: 28px;
|
width: 28px;
|
||||||
height: 28px;
|
height: 28px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
background-image: url("/src/assets/img/control/item_checked.png");
|
background-image: url('/src/assets/img/control/item_checked.png');
|
||||||
background-size: 80% 80%;
|
background-size: 80% 80%;
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-position: center;
|
background-position: center;
|
||||||
@@ -206,11 +215,11 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
|
|
||||||
&:hover:not(.active) ::before {
|
&:hover:not(.active) ::before {
|
||||||
content: "";
|
content: '';
|
||||||
width: 28px;
|
width: 28px;
|
||||||
height: 28px;
|
height: 28px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
background-image: url("@/assets/img/control/item_hover.png");
|
background-image: url('@/assets/img/control/item_hover.png');
|
||||||
background-size: 100% 100%;
|
background-size: 100% 100%;
|
||||||
z-index: 6;
|
z-index: 6;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,17 @@
|
|||||||
import type { App } from "vue"
|
import type { App } from 'vue'
|
||||||
import Button from "./button/index.vue"
|
import Button from './button/index.vue'
|
||||||
import Tabs from "./tabs/index.vue"
|
import Tabs from './tabs/index.vue'
|
||||||
import Tab from "./tab/index.vue"
|
import Tab from './tab/index.vue'
|
||||||
import Select from "./select/index.vue"
|
import Select from './select/index.vue'
|
||||||
import Option from "./option/index.vue"
|
import Option from './option/index.vue'
|
||||||
import Menu from "./menu/menu.vue"
|
import Menu from './menu/menu.vue'
|
||||||
import Checkbox from "./checkbox/index.vue"
|
import Checkbox from './checkbox/index.vue'
|
||||||
import Collapse from "./collapse/index.vue"
|
import Collapse from './collapse/index.vue'
|
||||||
import Dialog from "./dialog/index.vue"
|
import Dialog from './dialog/index.vue'
|
||||||
import Tooltip from "./tooltip/index.vue"
|
import Tooltip from './tooltip/index.vue'
|
||||||
import Iconselect from "./iconselect/index.vue"
|
import Iconselect from './iconselect/index.vue'
|
||||||
import Selection from "./selection/index.vue"
|
import Selection from './selection/index.vue'
|
||||||
import Slider from "./slider/index.vue"
|
import Slider from './slider/index.vue'
|
||||||
|
|
||||||
|
|
||||||
export const components = {
|
export const components = {
|
||||||
Button,
|
Button,
|
||||||
@@ -27,7 +26,7 @@ export const components = {
|
|||||||
Tooltip,
|
Tooltip,
|
||||||
Iconselect,
|
Iconselect,
|
||||||
Selection,
|
Selection,
|
||||||
Slider
|
Slider,
|
||||||
}
|
}
|
||||||
|
|
||||||
export type CalcComponents = typeof components
|
export type CalcComponents = typeof components
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<script lang="tsx">
|
<script lang="tsx">
|
||||||
import { HiItem } from "hoci"
|
import { HiItem } from 'hoci'
|
||||||
export default HiItem
|
export default HiItem
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,23 +1,26 @@
|
|||||||
<script lang="tsx">
|
<script lang="tsx">
|
||||||
import { computed, defineComponent, renderSlot } from "vue"
|
import { computed, defineComponent, renderSlot } from 'vue'
|
||||||
import { classPropType } from "@/components/hooks/types"
|
import { classPropType } from '@/components/hooks/types'
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
props: {
|
props: {
|
||||||
loading: {
|
loading: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: () => false
|
default: () => false,
|
||||||
},
|
},
|
||||||
class: {
|
class: {
|
||||||
type: classPropType,
|
type: classPropType,
|
||||||
default: () => ""
|
default: () => '',
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
setup(props, { slots }) {
|
setup(props, { slots }) {
|
||||||
const loading = computed(() => props.loading)
|
const loading = computed(() => props.loading)
|
||||||
return () => {
|
return () => {
|
||||||
return (
|
return (
|
||||||
<div class="relative">
|
<div class="relative">
|
||||||
<div v-show={loading.value} class="flex h-full w-full z-99 absolute items-center justify-center">
|
<div
|
||||||
|
v-show={loading.value}
|
||||||
|
class="flex h-full w-full z-99 absolute items-center justify-center"
|
||||||
|
>
|
||||||
<svg
|
<svg
|
||||||
class="i-loading-spin"
|
class="i-loading-spin"
|
||||||
version="1.1"
|
version="1.1"
|
||||||
@@ -29,25 +32,49 @@ export default defineComponent({
|
|||||||
xml:space="preserve"
|
xml:space="preserve"
|
||||||
>
|
>
|
||||||
<g>
|
<g>
|
||||||
<linearGradient id="right" gradientUnits="userSpaceOnUse" x1="150" y1="20" x2="150" y2="180">
|
<linearGradient
|
||||||
|
id="right"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
x1="150"
|
||||||
|
y1="20"
|
||||||
|
x2="150"
|
||||||
|
y2="180"
|
||||||
|
>
|
||||||
<stop offset="0" style="stop-color:transparent" />
|
<stop offset="0" style="stop-color:transparent" />
|
||||||
<stop offset="1" style="stop-color:currentColor" />
|
<stop offset="1" style="stop-color:currentColor" />
|
||||||
</linearGradient>
|
</linearGradient>
|
||||||
<path fill="url(#right)" d="M100,0v20c44.1,0,80,35.9,80,80c0,44.1-35.9,80-80,80v20c55.2,0,100-44.8,100-100S155.2,0,100,0z" />
|
<path
|
||||||
<linearGradient id="left" gradientUnits="userSpaceOnUse" x1="50" y1="0" x2="50" y2="180">
|
fill="url(#right)"
|
||||||
|
d="M100,0v20c44.1,0,80,35.9,80,80c0,44.1-35.9,80-80,80v20c55.2,0,100-44.8,100-100S155.2,0,100,0z"
|
||||||
|
/>
|
||||||
|
<linearGradient
|
||||||
|
id="left"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
x1="50"
|
||||||
|
y1="0"
|
||||||
|
x2="50"
|
||||||
|
y2="180"
|
||||||
|
>
|
||||||
<stop offset="0" style="stop-color:currentColor" />
|
<stop offset="0" style="stop-color:currentColor" />
|
||||||
<stop offset="1" style="stop-color:transparent" />
|
<stop offset="1" style="stop-color:transparent" />
|
||||||
</linearGradient>
|
</linearGradient>
|
||||||
<path fill="url(#left)" d="M20,100c0-44.1,35.9-80,80-80V0C44.8,0,0,44.8,0,100s44.8,100,100,100v-20C55.9,180,20,144.1,20,100z" />
|
<path
|
||||||
|
fill="url(#left)"
|
||||||
|
d="M20,100c0-44.1,35.9-80,80-80V0C44.8,0,0,44.8,0,100s44.8,100,100,100v-20C55.9,180,20,144.1,20,100z"
|
||||||
|
/>
|
||||||
<circle fill="currentColor" cx="100" cy="10" r="10" />
|
<circle fill="currentColor" cx="100" cy="10" r="10" />
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
<div class={[props.class].concat("duration-200").concat(loading.value ? "opacity-0" : "")}>{renderSlot(slots, "default", {}, () => [])}</div>
|
<div
|
||||||
|
class={[props.class].concat('duration-200').concat(loading.value ? 'opacity-0' : '')}
|
||||||
|
>
|
||||||
|
{renderSlot(slots, 'default', {}, () => [])}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
<script lang="tsx">
|
<script lang="tsx">
|
||||||
import { useToggle } from "@vueuse/core"
|
import { useToggle } from '@vueuse/core'
|
||||||
import { defineComponent, ref, renderSlot } from "vue"
|
import { defineComponent, ref, renderSlot } from 'vue'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "CalcMenu",
|
name: 'CalcMenu',
|
||||||
props: ["label"],
|
props: ['label'],
|
||||||
setup(props, { slots }) {
|
setup(props, { slots }) {
|
||||||
const expand = ref(false)
|
const expand = ref(false)
|
||||||
|
|
||||||
@@ -24,11 +24,13 @@ export default defineComponent({
|
|||||||
</div>
|
</div>
|
||||||
<div class="i-menu-label" v-trans={props.label}></div>
|
<div class="i-menu-label" v-trans={props.label}></div>
|
||||||
</div>
|
</div>
|
||||||
<div class={{ "i-menu-items": true, "expand": expand.value }}>{renderSlot(slots, "default")}</div>
|
<div class={{ 'i-menu-items': true, expand: expand.value }}>
|
||||||
|
{renderSlot(slots, 'default')}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<script lang="tsx">
|
<script lang="tsx">
|
||||||
import { HiItem } from "hoci"
|
import { HiItem } from 'hoci'
|
||||||
export default HiItem
|
export default HiItem
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,33 +1,35 @@
|
|||||||
<script lang="tsx">
|
<script lang="tsx">
|
||||||
import { onKeyStroke } from "@vueuse/core"
|
import { onKeyStroke } from '@vueuse/core'
|
||||||
import type { PropType } from "vue";
|
import type { PropType } from 'vue'
|
||||||
import { computed, defineComponent, onUnmounted } from "vue"
|
import { computed, defineComponent, onUnmounted } from 'vue'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
props: {
|
props: {
|
||||||
page: {
|
page: {
|
||||||
type: Number,
|
type: Number,
|
||||||
default: () => 0
|
default: () => 0,
|
||||||
},
|
},
|
||||||
totalPage: {
|
totalPage: {
|
||||||
type: Number,
|
type: Number,
|
||||||
default: () => 0
|
default: () => 0,
|
||||||
},
|
},
|
||||||
minPage: {
|
minPage: {
|
||||||
type: Number,
|
type: Number,
|
||||||
default: () => 1
|
default: () => 1,
|
||||||
},
|
},
|
||||||
parent: {
|
parent: {
|
||||||
type: Object as PropType<HTMLElement>,
|
type: Object as PropType<HTMLElement>,
|
||||||
default: () => document
|
default: () => document,
|
||||||
},
|
},
|
||||||
disabled: {
|
disabled: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false
|
default: false,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
setup(props, { emit }) {
|
setup(props, { emit }) {
|
||||||
const totalPage = computed(() => (Number.isNaN(props.totalPage) ? props.minPage : props.totalPage))
|
const totalPage = computed(() =>
|
||||||
|
Number.isNaN(props.totalPage) ? props.minPage : props.totalPage,
|
||||||
|
)
|
||||||
|
|
||||||
const page = computed({
|
const page = computed({
|
||||||
get() {
|
get() {
|
||||||
@@ -37,17 +39,16 @@ export default defineComponent({
|
|||||||
return Math.max(Math.min(props.page, totalPage.value), props.minPage)
|
return Math.max(Math.min(props.page, totalPage.value), props.minPage)
|
||||||
},
|
},
|
||||||
set(val) {
|
set(val) {
|
||||||
emit("update:page", val)
|
emit('update:page', val)
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
function prev(e: Event) {
|
function prev(e: Event) {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
if (page.value > 1 && !props.disabled) {
|
if (page.value > 1 && !props.disabled) {
|
||||||
page.value--
|
page.value--
|
||||||
emit("prev")
|
emit('prev')
|
||||||
emit("change", page.value)
|
emit('change', page.value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,13 +56,13 @@ export default defineComponent({
|
|||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
if (page.value < totalPage.value && !props.disabled) {
|
if (page.value < totalPage.value && !props.disabled) {
|
||||||
page.value = page.value + 1
|
page.value = page.value + 1
|
||||||
emit("next")
|
emit('next')
|
||||||
emit("change", page.value)
|
emit('change', page.value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const removePrev = onKeyStroke(["F1", "PageUp"], prev, { target: props.parent })
|
const removePrev = onKeyStroke(['F1', 'PageUp'], prev, { target: props.parent })
|
||||||
const removeNext = onKeyStroke(["F2", "PageDown"], next, { target: props.parent })
|
const removeNext = onKeyStroke(['F2', 'PageDown'], next, { target: props.parent })
|
||||||
|
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
removePrev()
|
removePrev()
|
||||||
@@ -71,15 +72,23 @@ export default defineComponent({
|
|||||||
return () => {
|
return () => {
|
||||||
return (
|
return (
|
||||||
<div class="flex space-x-1 h-10 w-full items-center justify-center">
|
<div class="flex space-x-1 h-10 w-full items-center justify-center">
|
||||||
<calc-button icon="prev" disabled={page.value <= 1 || props.disabled} onClick={prev}></calc-button>
|
<calc-button
|
||||||
|
icon="prev"
|
||||||
|
disabled={page.value <= 1 || props.disabled}
|
||||||
|
onClick={prev}
|
||||||
|
></calc-button>
|
||||||
<span class="text-center w-8">
|
<span class="text-center w-8">
|
||||||
{page.value}/{totalPage.value}
|
{page.value}/{totalPage.value}
|
||||||
</span>
|
</span>
|
||||||
<calc-button icon="next" disabled={page.value >= totalPage.value || props.disabled} onClick={next}></calc-button>
|
<calc-button
|
||||||
|
icon="next"
|
||||||
|
disabled={page.value >= totalPage.value || props.disabled}
|
||||||
|
onClick={next}
|
||||||
|
></calc-button>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
<script lang="tsx">
|
<script lang="tsx">
|
||||||
import { computed, defineComponent } from "vue"
|
import { computed, defineComponent } from 'vue'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
props: {
|
props: {
|
||||||
value: {
|
value: {
|
||||||
type: [Number, String],
|
type: [Number, String],
|
||||||
default: 0
|
default: 0,
|
||||||
},
|
},
|
||||||
|
|
||||||
total: {
|
total: {
|
||||||
type: [Number, String],
|
type: [Number, String],
|
||||||
default: 100
|
default: 100,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
setup(props) {
|
setup(props) {
|
||||||
const progress = computed(() => {
|
const progress = computed(() => {
|
||||||
@@ -24,16 +24,28 @@ export default defineComponent({
|
|||||||
return () => (
|
return () => (
|
||||||
<div class="border-solid bg-hex-171717 border-hex-272521 border-2">
|
<div class="border-solid bg-hex-171717 border-hex-272521 border-2">
|
||||||
<div class="border-transparent border-solid border-2">
|
<div class="border-transparent border-solid border-2">
|
||||||
<div style={progress.value == 0 ? "width:0" : `width:${progress.value.toFixed(2)}%`} class="h-2 duration-200 calc-progress"></div>
|
<div
|
||||||
|
style={progress.value == 0 ? 'width:0' : `width:${progress.value.toFixed(2)}%`}
|
||||||
|
class="h-2 duration-200 calc-progress"
|
||||||
|
></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.calc-progress {
|
.calc-progress {
|
||||||
background: linear-gradient(to bottom, #48d0eb 0%, #6cf4fe 15%, #4fbdfe 30%, #3080fe 40%, #1d5bfe 55%, #3283fd 70%, #000456 100%);
|
background: linear-gradient(
|
||||||
|
to bottom,
|
||||||
|
#48d0eb 0%,
|
||||||
|
#6cf4fe 15%,
|
||||||
|
#4fbdfe 30%,
|
||||||
|
#3080fe 40%,
|
||||||
|
#1d5bfe 55%,
|
||||||
|
#3283fd 70%,
|
||||||
|
#000456 100%
|
||||||
|
);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,57 +1,67 @@
|
|||||||
<script lang="tsx">
|
<script lang="tsx">
|
||||||
import { selectionEmits, selectionProps, useSelectionList } from "hoci"
|
import { selectionEmits, selectionProps, useSelectionList } from 'hoci'
|
||||||
import type { CSSProperties, PropType, RendererElement } from "vue";
|
import type { CSSProperties, PropType, RendererElement } from 'vue'
|
||||||
import { Teleport, Transition, computed, defineComponent, onDeactivated, ref, renderList, renderSlot, watch } from "vue"
|
import {
|
||||||
|
Teleport,
|
||||||
|
Transition,
|
||||||
|
computed,
|
||||||
|
defineComponent,
|
||||||
|
onDeactivated,
|
||||||
|
ref,
|
||||||
|
renderList,
|
||||||
|
renderSlot,
|
||||||
|
watch,
|
||||||
|
} from 'vue'
|
||||||
|
|
||||||
import { onClickOutside, useVModel } from "@vueuse/core"
|
import { onClickOutside, useVModel } from '@vueuse/core'
|
||||||
import { classPropType, labelPropType } from "@/components/hooks/types"
|
import { classPropType, labelPropType } from '@/components/hooks/types'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "ISelect",
|
name: 'ISelect',
|
||||||
props: {
|
props: {
|
||||||
...selectionProps,
|
...selectionProps,
|
||||||
disabled: {
|
disabled: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false
|
default: false,
|
||||||
},
|
},
|
||||||
width: {
|
width: {
|
||||||
type: Number,
|
type: Number,
|
||||||
default: 120
|
default: 120,
|
||||||
},
|
},
|
||||||
emptyLabel: {
|
emptyLabel: {
|
||||||
type: labelPropType
|
type: labelPropType,
|
||||||
},
|
},
|
||||||
highlight: {
|
highlight: {
|
||||||
type: String,
|
type: String,
|
||||||
// warn remind
|
// warn remind
|
||||||
default: ""
|
default: '',
|
||||||
},
|
},
|
||||||
labelClass: {
|
labelClass: {
|
||||||
type: String,
|
type: String,
|
||||||
default: ""
|
default: '',
|
||||||
},
|
},
|
||||||
inputClass: {
|
inputClass: {
|
||||||
type: classPropType,
|
type: classPropType,
|
||||||
default: ""
|
default: '',
|
||||||
},
|
},
|
||||||
appendTo: {
|
appendTo: {
|
||||||
type: [Object, String] as PropType<string | RendererElement | null | undefined>,
|
type: [Object, String] as PropType<string | RendererElement | null | undefined>,
|
||||||
default() {
|
default() {
|
||||||
return "body"
|
return 'body'
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
emits: [...selectionEmits],
|
emits: [...selectionEmits],
|
||||||
setup(props, context) {
|
setup(props, context) {
|
||||||
const modelValue = useVModel(props, "modelValue", context.emit, { passive: true })
|
const modelValue = useVModel(props, 'modelValue', context.emit, { passive: true })
|
||||||
|
|
||||||
const { renderItem } = useSelectionList(() => {
|
const { renderItem } = useSelectionList(() => {
|
||||||
return {
|
return {
|
||||||
...props,
|
...props,
|
||||||
modelValue: modelValue.value,
|
modelValue: modelValue.value,
|
||||||
itemClass: "i-select-dropdown-item",
|
itemClass: 'i-select-dropdown-item',
|
||||||
activeClass: "active",
|
activeClass: 'active',
|
||||||
unactiveClass: "unactive"
|
unactiveClass: 'unactive',
|
||||||
}
|
}
|
||||||
}, context)
|
}, context)
|
||||||
|
|
||||||
@@ -74,13 +84,13 @@ export default defineComponent({
|
|||||||
return {
|
return {
|
||||||
left: `${dropdownPosition.value.x}px`,
|
left: `${dropdownPosition.value.x}px`,
|
||||||
top: `${dropdownPosition.value.y}px`,
|
top: `${dropdownPosition.value.y}px`,
|
||||||
width: `${dropdownPosition.value.w}px`
|
width: `${dropdownPosition.value.w}px`,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return {
|
return {
|
||||||
left: `${dropdownPosition.value.x}px`,
|
left: `${dropdownPosition.value.x}px`,
|
||||||
bottom: `${dropdownPosition.value.z}px`,
|
bottom: `${dropdownPosition.value.z}px`,
|
||||||
width: `${dropdownPosition.value.w}px`
|
width: `${dropdownPosition.value.w}px`,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -93,32 +103,31 @@ export default defineComponent({
|
|||||||
w: width,
|
w: width,
|
||||||
x: left,
|
x: left,
|
||||||
y: top + height + 2,
|
y: top + height + 2,
|
||||||
z: 0
|
z: 0,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
dropdownPosition.value = {
|
dropdownPosition.value = {
|
||||||
w: width,
|
w: width,
|
||||||
x: left,
|
x: left,
|
||||||
z: window.innerHeight - top + 2,
|
z: window.innerHeight - top + 2,
|
||||||
y: 0
|
y: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const appendToRef = computed(() => {
|
const appendToRef = computed(() => {
|
||||||
return props.appendTo || "body"
|
return props.appendTo || 'body'
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
onClickOutside(triggerRef, () => (isOpen.value = false))
|
onClickOutside(triggerRef, () => (isOpen.value = false))
|
||||||
|
|
||||||
window.addEventListener("resize", onResize)
|
window.addEventListener('resize', onResize)
|
||||||
window.addEventListener("scroll", onResize)
|
window.addEventListener('scroll', onResize)
|
||||||
|
|
||||||
onDeactivated(() => {
|
onDeactivated(() => {
|
||||||
window.removeEventListener("resize", onResize)
|
window.removeEventListener('resize', onResize)
|
||||||
window.removeEventListener("scroll", onResize)
|
window.removeEventListener('scroll', onResize)
|
||||||
})
|
})
|
||||||
|
|
||||||
const { slots } = context
|
const { slots } = context
|
||||||
@@ -127,50 +136,64 @@ export default defineComponent({
|
|||||||
const children = renderItem()
|
const children = renderItem()
|
||||||
if (children) {
|
if (children) {
|
||||||
if (!Array.isArray(children)) {
|
if (!Array.isArray(children)) {
|
||||||
return <span class={["i-select-input"].concat(props.inputClass)}>{children}</span>
|
return <span class={['i-select-input'].concat(props.inputClass)}>{children}</span>
|
||||||
} else if (children.length > 0) {
|
} else if (children.length > 0) {
|
||||||
return (
|
return (
|
||||||
<span class={["i-select-input space-x-1"].concat(props.inputClass)}>
|
<span class={['i-select-input space-x-1'].concat(props.inputClass)}>
|
||||||
{renderList(children, item => (
|
{renderList(children, (item) => (
|
||||||
<span>{item}</span>
|
<span>{item}</span>
|
||||||
))}
|
))}
|
||||||
</span>
|
</span>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const emptyLabel = typeof props.emptyLabel == "function" ? props.emptyLabel() : props.emptyLabel
|
const emptyLabel =
|
||||||
|
typeof props.emptyLabel == 'function' ? props.emptyLabel() : props.emptyLabel
|
||||||
return <span class="w-full pl-2 i-select-input i-select-empty-label">{emptyLabel}</span>
|
return <span class="w-full pl-2 i-select-input i-select-empty-label">{emptyLabel}</span>
|
||||||
}
|
}
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
return (
|
return (
|
||||||
<div class={["min-w-20 w-40 i-select "].concat(props.highlight)} onClick={collapse} ref={selectRef}>
|
<div
|
||||||
|
class={['min-w-20 w-40 i-select '].concat(props.highlight)}
|
||||||
|
onClick={collapse}
|
||||||
|
ref={selectRef}
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
class={{
|
class={{
|
||||||
"i-select-trigger": true,
|
'i-select-trigger': true,
|
||||||
"disabled": props.disabled
|
disabled: props.disabled,
|
||||||
}}
|
}}
|
||||||
ref={triggerRef}
|
ref={triggerRef}
|
||||||
>
|
>
|
||||||
{renderLabel()}
|
{renderLabel()}
|
||||||
<calc-button disabled={props.disabled} icon="dropdown" class="cursor-pointer"></calc-button>
|
<calc-button
|
||||||
|
disabled={props.disabled}
|
||||||
|
icon="dropdown"
|
||||||
|
class="cursor-pointer"
|
||||||
|
></calc-button>
|
||||||
</div>
|
</div>
|
||||||
<Teleport to={appendToRef.value}>
|
<Teleport to={appendToRef.value}>
|
||||||
<Transition name="dropdown" mode="out-in">
|
<Transition name="dropdown" mode="out-in">
|
||||||
<div class="i-select-dropdown" style={dropdownStyle.value} v-show={isOpen.value} ref={dropdownRef}>
|
<div
|
||||||
{renderSlot(slots, "default")}
|
class="i-select-dropdown"
|
||||||
|
style={dropdownStyle.value}
|
||||||
|
v-show={isOpen.value}
|
||||||
|
ref={dropdownRef}
|
||||||
|
>
|
||||||
|
{renderSlot(slots, 'default')}
|
||||||
</div>
|
</div>
|
||||||
</Transition>
|
</Transition>
|
||||||
</Teleport>
|
</Teleport>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@use "sass:color";
|
@use 'sass:color';
|
||||||
$text-color: #937639;
|
$text-color: #937639;
|
||||||
.i-select {
|
.i-select {
|
||||||
min-width: 80px;
|
min-width: 80px;
|
||||||
@@ -267,7 +290,7 @@ export default defineComponent({
|
|||||||
color: #e9c556;
|
color: #e9c556;
|
||||||
}
|
}
|
||||||
&.active::after {
|
&.active::after {
|
||||||
content: "✓";
|
content: '✓';
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 5px;
|
right: 5px;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<script lang="tsx">
|
<script lang="tsx">
|
||||||
import { HiSelection } from "hoci"
|
import { HiSelection } from 'hoci'
|
||||||
|
|
||||||
export default HiSelection
|
export default HiSelection
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
import type { InjectionKey } from "vue";
|
import type { InjectionKey } from 'vue'
|
||||||
|
|
||||||
export const CHECKBOX_GROUP: InjectionKey<boolean> = Symbol("checkbox-group")
|
export const CHECKBOX_GROUP: InjectionKey<boolean> = Symbol('checkbox-group')
|
||||||
|
|||||||
@@ -3,37 +3,36 @@ import { defineComponent, ref, computed, shallowRef, watch } from 'vue'
|
|||||||
import { useVModel, useDraggable, clamp } from '@vueuse/core'
|
import { useVModel, useDraggable, clamp } from '@vueuse/core'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "ISlider",
|
name: 'ISlider',
|
||||||
props: {
|
props: {
|
||||||
modelValue: {
|
modelValue: {
|
||||||
type: Number,
|
type: Number,
|
||||||
default: 0
|
default: 0,
|
||||||
},
|
},
|
||||||
min: {
|
min: {
|
||||||
type: Number,
|
type: Number,
|
||||||
default: 0
|
default: 0,
|
||||||
},
|
},
|
||||||
max: {
|
max: {
|
||||||
type: Number,
|
type: Number,
|
||||||
default: 100
|
default: 100,
|
||||||
},
|
},
|
||||||
step: {
|
step: {
|
||||||
type: Number,
|
type: Number,
|
||||||
default: 1
|
default: 1,
|
||||||
},
|
},
|
||||||
disabled: {
|
disabled: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false
|
default: false,
|
||||||
},
|
},
|
||||||
showPercent: {
|
showPercent: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true
|
default: true,
|
||||||
},
|
},
|
||||||
formatValue: {
|
formatValue: {
|
||||||
type: Function,
|
type: Function,
|
||||||
default: undefined
|
default: undefined,
|
||||||
}
|
},
|
||||||
|
|
||||||
},
|
},
|
||||||
emits: ['update:modelValue', 'change'],
|
emits: ['update:modelValue', 'change'],
|
||||||
setup(props, { emit }) {
|
setup(props, { emit }) {
|
||||||
@@ -57,7 +56,10 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 使用runway的位置和宽度来计算百分比
|
// 使用runway的位置和宽度来计算百分比
|
||||||
const percentage = Math.max(0, Math.min(100, ((position.x - runwayRect.left) / runwayRect.width) * 100))
|
const percentage = Math.max(
|
||||||
|
0,
|
||||||
|
Math.min(100, ((position.x - runwayRect.left) / runwayRect.width) * 100),
|
||||||
|
)
|
||||||
|
|
||||||
const range = props.max - props.min
|
const range = props.max - props.min
|
||||||
let value = (percentage * range) / 100 + props.min
|
let value = (percentage * range) / 100 + props.min
|
||||||
@@ -70,20 +72,17 @@ export default defineComponent({
|
|||||||
|
|
||||||
modelValue.value = value
|
modelValue.value = value
|
||||||
emit('change', value)
|
emit('change', value)
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
return () => (
|
return () => (
|
||||||
<div
|
<div
|
||||||
class={[
|
class={[
|
||||||
'w-full h-8 relative cursor-pointer flex items-center gap-3 py-2',
|
'w-full h-8 relative cursor-pointer flex items-center gap-3 py-2',
|
||||||
{ 'cursor-not-allowed': props.disabled }
|
{ 'cursor-not-allowed': props.disabled },
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<div
|
<div class="flex-1 h-1 bg-[#4D524D] relative" ref={runwayRef}>
|
||||||
class="flex-1 h-1 bg-[#4D524D] relative"
|
|
||||||
ref={runwayRef}
|
|
||||||
>
|
|
||||||
<div
|
<div
|
||||||
class="h-1 bg-[#8E6D28] absolute left-0 top-0"
|
class="h-1 bg-[#8E6D28] absolute left-0 top-0"
|
||||||
style={{ width: `${percentage.value}%` }}
|
style={{ width: `${percentage.value}%` }}
|
||||||
@@ -93,26 +92,32 @@ export default defineComponent({
|
|||||||
style={{ left: `calc(${percentage.value}% - 0.75rem)` }}
|
style={{ left: `calc(${percentage.value}% - 0.75rem)` }}
|
||||||
ref={buttonRef}
|
ref={buttonRef}
|
||||||
>
|
>
|
||||||
<div class={[
|
<div
|
||||||
|
class={[
|
||||||
'w-4 h-4 absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2',
|
'w-4 h-4 absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2',
|
||||||
'bg-gradient-to-b from-[#223768] to-[#122438]',
|
'bg-gradient-to-b from-[#223768] to-[#122438]',
|
||||||
'border border-solid border-[#937639] rounded-full transition-all duration-200',
|
'border border-solid border-[#937639] rounded-full transition-all duration-200',
|
||||||
'shadow-[0_2px_4px_rgba(0,0,0,0.2)]',
|
'shadow-[0_2px_4px_rgba(0,0,0,0.2)]',
|
||||||
{ 'bg-gradient-to-b from-[#353535] to-[#1c1c1c] border-[#414141]': props.disabled }
|
{ 'bg-gradient-to-b from-[#353535] to-[#1c1c1c] border-[#414141]': props.disabled },
|
||||||
]}></div>
|
]}
|
||||||
|
></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{props.showPercent && (
|
{props.showPercent && (
|
||||||
<div class={[
|
<div
|
||||||
|
class={[
|
||||||
'w-auto min-w-5 text-center text-sm font-medium',
|
'w-auto min-w-5 text-center text-sm font-medium',
|
||||||
props.disabled ? 'text-[#696969]' : 'text-[#e9c556]'
|
props.disabled ? 'text-[#696969]' : 'text-[#e9c556]',
|
||||||
]}>
|
]}
|
||||||
{props.formatValue ? props.formatValue(modelValue.value) : `${percentage.value.toFixed(0)}%`}
|
>
|
||||||
|
{props.formatValue
|
||||||
|
? props.formatValue(modelValue.value)
|
||||||
|
: `${percentage.value.toFixed(0)}%`}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -204,4 +209,3 @@ export default defineComponent({
|
|||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
<script lang="tsx">
|
<script lang="tsx">
|
||||||
import { defineComponent, renderSlot } from "vue"
|
import { defineComponent, renderSlot } from 'vue'
|
||||||
import { HiItem, selectionProps } from "hoci"
|
import { HiItem, selectionProps } from 'hoci'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "CalcTab",
|
name: 'CalcTab',
|
||||||
props: {
|
props: {
|
||||||
...selectionProps
|
...selectionProps,
|
||||||
},
|
},
|
||||||
setup(props, { slots }) {
|
setup(props, { slots }) {
|
||||||
return () => {
|
return () => {
|
||||||
return <HiItem {...props}>{renderSlot(slots, "default")}</HiItem>
|
return <HiItem {...props}>{renderSlot(slots, 'default')}</HiItem>
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
export const AciveSymbol = Symbol("[i-tabs]active")
|
export const AciveSymbol = Symbol('[i-tabs]active')
|
||||||
|
|
||||||
export const AciveClassSymbol = Symbol("[i-tabs]active-class")
|
export const AciveClassSymbol = Symbol('[i-tabs]active-class')
|
||||||
|
|
||||||
export const ChangeActiveSymbol = Symbol("[i-tabs]change-active")
|
export const ChangeActiveSymbol = Symbol('[i-tabs]change-active')
|
||||||
|
|||||||
@@ -1,30 +1,30 @@
|
|||||||
<script lang="tsx">
|
<script lang="tsx">
|
||||||
import { HiSelection, selectionProps } from "hoci"
|
import { HiSelection, selectionProps } from 'hoci'
|
||||||
import type { PropType } from "vue";
|
import type { PropType } from 'vue'
|
||||||
import { computed, defineComponent, renderSlot } from "vue"
|
import { computed, defineComponent, renderSlot } from 'vue'
|
||||||
import type { LocationQuery } from "vue-router";
|
import type { LocationQuery } from 'vue-router'
|
||||||
import { parseQuery, useRouter } from "vue-router"
|
import { parseQuery, useRouter } from 'vue-router'
|
||||||
import type { BaseType } from "@/components/hooks/types"
|
import type { BaseType } from '@/components/hooks/types'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "CalcTabs",
|
name: 'CalcTabs',
|
||||||
props: {
|
props: {
|
||||||
...selectionProps,
|
...selectionProps,
|
||||||
vertical: {
|
vertical: {
|
||||||
type: Boolean
|
type: Boolean,
|
||||||
},
|
},
|
||||||
route: {
|
route: {
|
||||||
type: Boolean
|
type: Boolean,
|
||||||
},
|
},
|
||||||
query: {
|
query: {
|
||||||
type: [Object, String] as PropType<string | LocationQuery>
|
type: [Object, String] as PropType<string | LocationQuery>,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
setup(props, { emit, slots }) {
|
setup(props, { emit, slots }) {
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
const routeQuery = computed(() => {
|
const routeQuery = computed(() => {
|
||||||
if (typeof props.query == "string") {
|
if (typeof props.query == 'string') {
|
||||||
return parseQuery(props.query)
|
return parseQuery(props.query)
|
||||||
}
|
}
|
||||||
return props.query ?? {}
|
return props.query ?? {}
|
||||||
@@ -43,19 +43,24 @@ export default defineComponent({
|
|||||||
val = decodeURIComponent(val.toString())
|
val = decodeURIComponent(val.toString())
|
||||||
router.push({ path: val, query: routeQuery.value })
|
router.push({ path: val, query: routeQuery.value })
|
||||||
}
|
}
|
||||||
emit("update:modelValue", val)
|
emit('update:modelValue', val)
|
||||||
emit("change", val)
|
emit('change', val)
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
return (
|
return (
|
||||||
<HiSelection v-model={modelValue.value} class={{ "i-tabs": true, "vertical": !!props.vertical }} activeClass="active" itemClass={["i-tab cursor-pointer"].concat(props.itemClass)}>
|
<HiSelection
|
||||||
{renderSlot(slots, "default")}
|
v-model={modelValue.value}
|
||||||
|
class={{ 'i-tabs': true, vertical: !!props.vertical }}
|
||||||
|
activeClass="active"
|
||||||
|
itemClass={['i-tab cursor-pointer'].concat(props.itemClass)}
|
||||||
|
>
|
||||||
|
{renderSlot(slots, 'default')}
|
||||||
</HiSelection>
|
</HiSelection>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -115,7 +120,7 @@ export default defineComponent({
|
|||||||
|
|
||||||
&.active {
|
&.active {
|
||||||
background: linear-gradient(#574d38, #25221d);
|
background: linear-gradient(#574d38, #25221d);
|
||||||
border-image: url("@/assets/img/control/active_top.png") 1 fill stretch;
|
border-image: url('@/assets/img/control/active_top.png') 1 fill stretch;
|
||||||
// color: #ffb400;
|
// color: #ffb400;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,24 +1,27 @@
|
|||||||
<script lang="tsx">
|
<script lang="tsx">
|
||||||
import { defineComponent } from "vue"
|
import { defineComponent } from 'vue'
|
||||||
import { NTooltip } from "@/components/base"
|
import { NTooltip } from '@/components/base'
|
||||||
|
|
||||||
import { tooltipProps } from "@/components/base/tooltip"
|
import { tooltipProps } from '@/components/base/tooltip'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "ITooltip",
|
name: 'ITooltip',
|
||||||
components: { NTooltip },
|
components: { NTooltip },
|
||||||
props: {
|
props: {
|
||||||
...tooltipProps
|
...tooltipProps,
|
||||||
},
|
},
|
||||||
setup(props, { slots }) {
|
setup(props, { slots }) {
|
||||||
return () => {
|
return () => {
|
||||||
return (
|
return (
|
||||||
<n-tooltip {...props} pop-class="i-popper z-999 fixed top-0 left-0 bg-black bg-opacity-90 border-1.5 border-hex-272928 rounded-2px border-solid">
|
<n-tooltip
|
||||||
|
{...props}
|
||||||
|
pop-class="i-popper z-999 fixed top-0 left-0 bg-black bg-opacity-90 border-1.5 border-hex-272928 rounded-2px border-solid"
|
||||||
|
>
|
||||||
{slots}
|
{slots}
|
||||||
</n-tooltip>
|
</n-tooltip>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -1,55 +1,55 @@
|
|||||||
<script lang="tsx">
|
<script lang="tsx">
|
||||||
import { HiSelection, selectionProps } from "hoci"
|
import { HiSelection, selectionProps } from 'hoci'
|
||||||
import { useVModel } from "@vueuse/core"
|
import { useVModel } from '@vueuse/core'
|
||||||
import type { PropType } from "vue";
|
import type { PropType } from 'vue'
|
||||||
import { computed, defineComponent, renderList, watch } from "vue"
|
import { computed, defineComponent, renderList, watch } from 'vue'
|
||||||
import CalcTreeNode from "./node.vue"
|
import CalcTreeNode from './node.vue'
|
||||||
import type { TreeNode } from "./types"
|
import type { TreeNode } from './types'
|
||||||
import { labelPropType, valuePropType } from "@/components/hooks/types"
|
import { labelPropType, valuePropType } from '@/components/hooks/types'
|
||||||
|
|
||||||
const Tree = defineComponent({
|
const Tree = defineComponent({
|
||||||
name: "CalcTree",
|
name: 'CalcTree',
|
||||||
props: {
|
props: {
|
||||||
...selectionProps,
|
...selectionProps,
|
||||||
modelValue: {
|
modelValue: {
|
||||||
type: valuePropType,
|
type: valuePropType,
|
||||||
default: () => null
|
default: () => null,
|
||||||
},
|
},
|
||||||
activeItem: {
|
activeItem: {
|
||||||
type: Object as PropType<TreeNode>,
|
type: Object as PropType<TreeNode>,
|
||||||
default: () => null
|
default: () => null,
|
||||||
},
|
},
|
||||||
idKey: {
|
idKey: {
|
||||||
type: String,
|
type: String,
|
||||||
default: "id"
|
default: 'id',
|
||||||
},
|
},
|
||||||
label: {
|
label: {
|
||||||
type: labelPropType
|
type: labelPropType,
|
||||||
},
|
},
|
||||||
data: {
|
data: {
|
||||||
type: Array as PropType<TreeNode[]>,
|
type: Array as PropType<TreeNode[]>,
|
||||||
default: () => []
|
default: () => [],
|
||||||
},
|
},
|
||||||
depth: {
|
depth: {
|
||||||
type: [Number, String] as PropType<number>,
|
type: [Number, String] as PropType<number>,
|
||||||
default: () => 0
|
default: () => 0,
|
||||||
},
|
},
|
||||||
depthStyle: {
|
depthStyle: {
|
||||||
type: Function as PropType<(depth: number) => string>
|
type: Function as PropType<(depth: number) => string>,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
setup(props, { emit }) {
|
setup(props, { emit }) {
|
||||||
const modelValue = useVModel(props, "modelValue")
|
const modelValue = useVModel(props, 'modelValue')
|
||||||
|
|
||||||
function onSelect(item?: TreeNode) {
|
function onSelect(item?: TreeNode) {
|
||||||
if (item) {
|
if (item) {
|
||||||
emit("select", item)
|
emit('select', item)
|
||||||
item.onSelect?.()
|
item.onSelect?.()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadItem(total: TreeNode[], items: TreeNode[]) {
|
function loadItem(total: TreeNode[], items: TreeNode[]) {
|
||||||
items?.forEach(item => {
|
items?.forEach((item) => {
|
||||||
if (item.children) {
|
if (item.children) {
|
||||||
loadItem(total, item.children)
|
loadItem(total, item.children)
|
||||||
}
|
}
|
||||||
@@ -62,22 +62,34 @@ const Tree = defineComponent({
|
|||||||
return loadItem([], props.data)
|
return loadItem([], props.data)
|
||||||
})
|
})
|
||||||
|
|
||||||
watch(modelValue, val => {
|
watch(modelValue, (val) => {
|
||||||
val = val ?? props.defaultValue
|
val = val ?? props.defaultValue
|
||||||
const item = children.value.find(item => item.value === val)
|
const item = children.value.find((item) => item.value === val)
|
||||||
onSelect(item)
|
onSelect(item)
|
||||||
})
|
})
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
return (
|
return (
|
||||||
<HiSelection {...props} activeClass="i-tree-node-active" v-model={modelValue.value} class="i-tree">
|
<HiSelection
|
||||||
{renderList(props.data, item => {
|
{...props}
|
||||||
return <CalcTreeNode {...item} onSelect={onSelect} depth-style={props.depthStyle} depth={props.depth} />
|
activeClass="i-tree-node-active"
|
||||||
|
v-model={modelValue.value}
|
||||||
|
class="i-tree"
|
||||||
|
>
|
||||||
|
{renderList(props.data, (item) => {
|
||||||
|
return (
|
||||||
|
<CalcTreeNode
|
||||||
|
{...item}
|
||||||
|
onSelect={onSelect}
|
||||||
|
depth-style={props.depthStyle}
|
||||||
|
depth={props.depth}
|
||||||
|
/>
|
||||||
|
)
|
||||||
})}
|
})}
|
||||||
</HiSelection>
|
</HiSelection>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
export default Tree
|
export default Tree
|
||||||
|
|||||||
@@ -1,34 +1,34 @@
|
|||||||
<script lang="tsx">
|
<script lang="tsx">
|
||||||
import { HiItem } from "hoci"
|
import { HiItem } from 'hoci'
|
||||||
import type { PropType } from "vue";
|
import type { PropType } from 'vue'
|
||||||
import { Transition, computed, defineComponent, ref, renderList } from "vue"
|
import { Transition, computed, defineComponent, ref, renderList } from 'vue'
|
||||||
import type { TreeNode } from "./types"
|
import type { TreeNode } from './types'
|
||||||
|
|
||||||
const NTreeNode = defineComponent({
|
const NTreeNode = defineComponent({
|
||||||
props: {
|
props: {
|
||||||
label: {
|
label: {
|
||||||
type: String,
|
type: String,
|
||||||
default: ""
|
default: '',
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
type: [String, Number, Boolean, Object, Array] as PropType<any>,
|
type: [String, Number, Boolean, Object, Array] as PropType<any>,
|
||||||
default: () => null
|
default: () => null,
|
||||||
},
|
},
|
||||||
children: {
|
children: {
|
||||||
type: Array as PropType<TreeNode[]>,
|
type: Array as PropType<TreeNode[]>,
|
||||||
default: () => []
|
default: () => [],
|
||||||
},
|
},
|
||||||
depth: {
|
depth: {
|
||||||
type: [String, Number] as PropType<number>,
|
type: [String, Number] as PropType<number>,
|
||||||
default: 0
|
default: 0,
|
||||||
},
|
},
|
||||||
depthStyle: {
|
depthStyle: {
|
||||||
type: Function as PropType<(depth: number) => string>
|
type: Function as PropType<(depth: number) => string>,
|
||||||
},
|
},
|
||||||
depthOffset: {
|
depthOffset: {
|
||||||
type: String,
|
type: String,
|
||||||
default: "12px"
|
default: '12px',
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
setup(props, { emit }) {
|
setup(props, { emit }) {
|
||||||
const isOpen = ref(false)
|
const isOpen = ref(false)
|
||||||
@@ -39,7 +39,7 @@ const NTreeNode = defineComponent({
|
|||||||
}
|
}
|
||||||
|
|
||||||
function onSelect(item: TreeNode) {
|
function onSelect(item: TreeNode) {
|
||||||
return emit("select", item)
|
return emit('select', item)
|
||||||
}
|
}
|
||||||
|
|
||||||
const depthStyle = computed(() => {
|
const depthStyle = computed(() => {
|
||||||
@@ -51,22 +51,31 @@ const NTreeNode = defineComponent({
|
|||||||
|
|
||||||
return () => (
|
return () => (
|
||||||
<div class="w-full i-tree-item relative">
|
<div class="w-full i-tree-item relative">
|
||||||
<HiItem label={props.label} value={props.value} style={depthStyle.value} class="flex i-tree-item-label items-center" onClick={open}>
|
<HiItem
|
||||||
|
label={props.label}
|
||||||
|
value={props.value}
|
||||||
|
style={depthStyle.value}
|
||||||
|
class="flex i-tree-item-label items-center"
|
||||||
|
onClick={open}
|
||||||
|
>
|
||||||
<div class="top-0 right-0 bottom-0 left-0 absolute i-tree-item-active-mask"></div>
|
<div class="top-0 right-0 bottom-0 left-0 absolute i-tree-item-active-mask"></div>
|
||||||
<div class="top-0 right-0 bottom-0 left-0 absolute i-tree-item-mask"></div>
|
<div class="top-0 right-0 bottom-0 left-0 absolute i-tree-item-mask"></div>
|
||||||
<calc-button v-show={props.children?.length} icon={isOpen.value ? "collapse-up" : "collapse-down"}></calc-button>
|
<calc-button
|
||||||
|
v-show={props.children?.length}
|
||||||
|
icon={isOpen.value ? 'collapse-up' : 'collapse-down'}
|
||||||
|
></calc-button>
|
||||||
<div class="pl-1">{props.label}</div>
|
<div class="pl-1">{props.label}</div>
|
||||||
</HiItem>
|
</HiItem>
|
||||||
<Transition name="dropdown" mode="out-in">
|
<Transition name="dropdown" mode="out-in">
|
||||||
<div v-show={isOpen.value}>
|
<div v-show={isOpen.value}>
|
||||||
{renderList(props.children, item => {
|
{renderList(props.children, (item) => {
|
||||||
return <NTreeNode onSelect={onSelect} {...item} depth={Number(props.depth) + 1} />
|
return <NTreeNode onSelect={onSelect} {...item} depth={Number(props.depth) + 1} />
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
</Transition>
|
</Transition>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
export default NTreeNode
|
export default NTreeNode
|
||||||
@@ -90,21 +99,21 @@ export default NTreeNode
|
|||||||
position: relative;
|
position: relative;
|
||||||
&:hover {
|
&:hover {
|
||||||
.i-tree-item-mask {
|
.i-tree-item-mask {
|
||||||
background: url("./img/item_hover.png") no-repeat;
|
background: url('./img/item_hover.png') no-repeat;
|
||||||
background-size: 100% 100%;
|
background-size: 100% 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.i-tree-node-active {
|
&.i-tree-node-active {
|
||||||
.i-tree-item-active-mask {
|
.i-tree-item-active-mask {
|
||||||
background: url("./img/item_active.png") no-repeat;
|
background: url('./img/item_active.png') no-repeat;
|
||||||
background-size: 100% 100%;
|
background-size: 100% 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-collapse-up {
|
.icon-collapse-up {
|
||||||
background-image: url("./img/collapse_up.png");
|
background-image: url('./img/collapse_up.png');
|
||||||
background-size: 100% 100%;
|
background-size: 100% 100%;
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-position: center;
|
background-position: center;
|
||||||
@@ -114,7 +123,7 @@ export default NTreeNode
|
|||||||
}
|
}
|
||||||
|
|
||||||
.icon-collapse-down {
|
.icon-collapse-down {
|
||||||
background-image: url("./img/collapse_down.png");
|
background-image: url('./img/collapse_down.png');
|
||||||
background-size: 100% 100%;
|
background-size: 100% 100%;
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-position: center;
|
background-position: center;
|
||||||
|
|||||||
@@ -39,8 +39,7 @@ const infoStyle = (part: string) => {
|
|||||||
if (part == '宠物') {
|
if (part == '宠物') {
|
||||||
x += 5 * 39
|
x += 5 * 39
|
||||||
y += 1 * 40
|
y += 1 * 40
|
||||||
}
|
} else if (part.includes('宠物装备')) {
|
||||||
else if (part.includes('宠物装备')) {
|
|
||||||
x += 6 * 39
|
x += 6 * 39
|
||||||
y += (index - infoStore.avatarParts.findIndex((p) => p == '宠物装备-红')) * 40
|
y += (index - infoStore.avatarParts.findIndex((p) => p == '宠物装备-红')) * 40
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
<template>
|
<template>
|
||||||
<template v-if="props.equipment">
|
<template v-if="props.equipment">
|
||||||
<div class="relative" :class="{ inactive: props.inactive }">
|
<div class="relative" :class="{ inactive: props.inactive }">
|
||||||
<div class="w-28px h-28px " :style="{ backgroundImage: `url(${getImageURL(props.equipment?.imageUrl)})` }">
|
<div
|
||||||
|
class="w-28px h-28px"
|
||||||
|
:style="{ backgroundImage: `url(${getImageURL(props.equipment?.imageUrl)})` }"
|
||||||
|
>
|
||||||
<img :src="getLocalImageURL(rarity)" />
|
<img :src="getLocalImageURL(rarity)" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -9,12 +12,10 @@
|
|||||||
<template v-else>
|
<template v-else>
|
||||||
<div class="w-26px h-26px border-1px border-solid border-#7a7a7a/50"></div>
|
<div class="w-26px h-26px border-1px border-solid border-#7a7a7a/50"></div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { IEquipment } from '@/api/info/type';
|
import type { IEquipment } from '@/api/info/type'
|
||||||
import { getImageURL } from '@/utils/images'
|
import { getImageURL } from '@/utils/images'
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
@@ -42,11 +43,10 @@ const rarity = computed(()=>{
|
|||||||
const getLocalImageURL = (rarity: string) => {
|
const getLocalImageURL = (rarity: string) => {
|
||||||
return new URL(`./rarity/${rarity}.png`, import.meta.url).href
|
return new URL(`./rarity/${rarity}.png`, import.meta.url).href
|
||||||
}
|
}
|
||||||
|
</script>
|
||||||
</script>``
|
``
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|
||||||
// @keyframes primeval {
|
// @keyframes primeval {
|
||||||
// @for $i from 0 through 29 {
|
// @for $i from 0 through 29 {
|
||||||
// #{percentage($i / 29)} {
|
// #{percentage($i / 29)} {
|
||||||
@@ -78,5 +78,4 @@ const getLocalImageURL = (rarity:string)=>{
|
|||||||
// filter: grayscale(100%);
|
// filter: grayscale(100%);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -30,27 +30,33 @@
|
|||||||
</div>
|
</div>
|
||||||
<!-- 装备基础信息 -->
|
<!-- 装备基础信息 -->
|
||||||
<div class="divide"></div>
|
<div class="divide"></div>
|
||||||
<div class="flex flex-col items-start my-1px" style="white-space: pre-wrap; line-height: 15px">
|
<div
|
||||||
|
class="flex flex-col items-start my-1px"
|
||||||
|
style="white-space: pre-wrap; line-height: 15px"
|
||||||
|
>
|
||||||
<div class="text-#908150" v-html="mainAttr"></div>
|
<div class="text-#908150" v-html="mainAttr"></div>
|
||||||
</div>
|
</div>
|
||||||
<!-- 装备属性 -->
|
<!-- 装备属性 -->
|
||||||
<div class="divide"></div>
|
<div class="divide"></div>
|
||||||
<div class="flex flex-col items-start my-1px" style="white-space: pre-wrap; line-height: 15px">
|
<div
|
||||||
|
class="flex flex-col items-start my-1px"
|
||||||
|
style="white-space: pre-wrap; line-height: 15px"
|
||||||
|
>
|
||||||
<div class="text-#DED29A" v-html="detail"></div>
|
<div class="text-#DED29A" v-html="detail"></div>
|
||||||
</div>
|
</div>
|
||||||
<template v-if="bufferDetail">
|
<template v-if="bufferDetail">
|
||||||
<div class="divide"></div>
|
<div class="divide"></div>
|
||||||
<div class="flex flex-col items-start my-1px" style="white-space: pre-wrap; line-height: 15px">
|
<div
|
||||||
|
class="flex flex-col items-start my-1px"
|
||||||
|
style="white-space: pre-wrap; line-height: 15px"
|
||||||
|
>
|
||||||
<div class="text-#A48B2E mb-10px">辅助职业专属属性</div>
|
<div class="text-#A48B2E mb-10px">辅助职业专属属性</div>
|
||||||
<div class="text-#DED29A" v-html="bufferDetail"></div>
|
<div class="text-#DED29A" v-html="bufferDetail"></div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<!-- 奶系专属 -->
|
<!-- 奶系专属 -->
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -66,28 +72,43 @@ const props = defineProps<{
|
|||||||
const rarity = computed(() => rarityClass(props.equipment?.rarity ?? ''))
|
const rarity = computed(() => rarityClass(props.equipment?.rarity ?? ''))
|
||||||
|
|
||||||
const mainAttr = computed(() => {
|
const mainAttr = computed(() => {
|
||||||
const attrs :(keyof IEquipment)[] = ['STR', 'INT', 'Vitality', 'Spirit','AtkP','AtkM','AtkI','SkillAttack','Attack','Buffer']
|
const attrs: (keyof IEquipment)[] = [
|
||||||
let info = ""
|
'STR',
|
||||||
|
'INT',
|
||||||
|
'Vitality',
|
||||||
|
'Spirit',
|
||||||
|
'AtkP',
|
||||||
|
'AtkM',
|
||||||
|
'AtkI',
|
||||||
|
'SkillAttack',
|
||||||
|
'Attack',
|
||||||
|
'Buffer',
|
||||||
|
]
|
||||||
|
let info = ''
|
||||||
for (const attr of attrs) {
|
for (const attr of attrs) {
|
||||||
const item = props.equipment?.[attr] as number[]
|
const item = props.equipment?.[attr] as number[]
|
||||||
if (item?.[0]) {
|
if (item?.[0]) {
|
||||||
info += `${formatAttr(attr, item?.[0])}\n`
|
info += `${formatAttr(attr, item?.[0])}\n`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return info;
|
return info
|
||||||
|
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const detail = computed(()=>props.equipment?.detail.replace(/\[([^\[\]技能]+?)\]/g, '<span style="color:#3d9147">[$1]</span>'))
|
const detail = computed(() =>
|
||||||
|
props.equipment?.detail.replace(
|
||||||
|
/\[([^\[\]技能]+?)\]/g,
|
||||||
|
'<span style="color:#3d9147">[$1]</span>',
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
const bufferDetail = computed(()=>
|
const bufferDetail = computed(() => {
|
||||||
{
|
|
||||||
const detail = props.equipment?.bufferDetail
|
const detail = props.equipment?.bufferDetail
|
||||||
if (!detail || detail == '-') return undefined
|
if (!detail || detail == '-') return undefined
|
||||||
return props.equipment?.bufferDetail.replace(/\[([^\[\]技能]+?)\]/g, '<span style="color:#3d9147">[$1]</span>')
|
return props.equipment?.bufferDetail.replace(
|
||||||
|
/\[([^\[\]技能]+?)\]/g,
|
||||||
|
'<span style="color:#3d9147">[$1]</span>',
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|||||||
@@ -23,15 +23,13 @@
|
|||||||
<div
|
<div
|
||||||
v-if="props.withSubWeapon"
|
v-if="props.withSubWeapon"
|
||||||
class="pos-absolute text-white/50 w-26px h-26px border-1px border-solid border-#7a7a7a/50 flex items-center justify-center"
|
class="pos-absolute text-white/50 w-26px h-26px border-1px border-solid border-#7a7a7a/50 flex items-center justify-center"
|
||||||
style="left:150px;top:5px;z-index:8;"
|
style="left: 150px; top: 5px; z-index: 8"
|
||||||
@click="choosePart('副武器')"
|
@click="choosePart('副武器')"
|
||||||
>
|
>
|
||||||
<template v-if="detail?.['副武器']?.id">
|
<template v-if="detail?.['副武器']?.id">
|
||||||
<EquipmentIcon :equipment="equ(detail['副武器'].id)" />
|
<EquipmentIcon :equipment="equ(detail['副武器'].id)" />
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else> 副武 </template>
|
||||||
副武
|
|
||||||
</template>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -61,7 +59,7 @@ const props = defineProps({
|
|||||||
withSubWeapon: {
|
withSubWeapon: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false,
|
default: false,
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
const partModelValue = useVModel(props, 'part')
|
const partModelValue = useVModel(props, 'part')
|
||||||
const infoStore = useInfoStore()
|
const infoStore = useInfoStore()
|
||||||
|
|||||||
@@ -1,11 +1,16 @@
|
|||||||
<template>
|
<template>
|
||||||
<calc-cascader class="!h-5 flex-1" v-model="selected" :items="items" placeholder="请输入名称搜索"></calc-cascader>
|
<calc-cascader
|
||||||
|
class="!h-5 flex-1"
|
||||||
|
v-model="selected"
|
||||||
|
:items="items"
|
||||||
|
placeholder="请输入名称搜索"
|
||||||
|
></calc-cascader>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { TreeNode } from "@/components/calc/tree/types"
|
import type { TreeNode } from '@/components/calc/tree/types'
|
||||||
import { useInfoStore } from "@/stores"
|
import { useInfoStore } from '@/stores'
|
||||||
import { syncRef, useVModel } from "@vueuse/core"
|
import { syncRef, useVModel } from '@vueuse/core'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
partList: {
|
partList: {
|
||||||
@@ -24,9 +29,9 @@ const else_parts = ['称号', '宠物']
|
|||||||
|
|
||||||
const emit = defineEmits([])
|
const emit = defineEmits([])
|
||||||
|
|
||||||
const choose_part = useVModel(props, "partList",emit,{passive:true})
|
const choose_part = useVModel(props, 'partList', emit, { passive: true })
|
||||||
|
|
||||||
const selected = ref("")
|
const selected = ref('')
|
||||||
|
|
||||||
const infoStore = useInfoStore()
|
const infoStore = useInfoStore()
|
||||||
|
|
||||||
|
|||||||
@@ -1,49 +1,55 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex gap-8px">
|
<div class="flex gap-8px">
|
||||||
<template v-for="(rarity, _) in rarities" :key="_">
|
<template v-for="(rarity, _) in rarities" :key="_">
|
||||||
<div class="w-14px h-14px shadow-[0px_0px_3px_#ffffff_inset,0px_0px_1px_#ffffff40]" :style="{background: rarity.background}" @click="choose(rarity.value)">
|
<div
|
||||||
<div class="w-14px h-14px" :class="{'active': value === rarity.value}"></div>
|
class="w-14px h-14px shadow-[0px_0px_3px_#ffffff_inset,0px_0px_1px_#ffffff40]"
|
||||||
|
:style="{ background: rarity.background }"
|
||||||
|
@click="choose(rarity.value)"
|
||||||
|
>
|
||||||
|
<div class="w-14px h-14px" :class="{ active: value === rarity.value }"></div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
|
||||||
const props = defineProps({})
|
const props = defineProps({})
|
||||||
|
|
||||||
const value = defineModel<string>()
|
const value = defineModel<string>()
|
||||||
|
|
||||||
const rarities = [{
|
const rarities = [
|
||||||
|
{
|
||||||
value: '稀有',
|
value: '稀有',
|
||||||
background: '#d06eff',
|
background: '#d06eff',
|
||||||
},{
|
},
|
||||||
|
{
|
||||||
value: '神器',
|
value: '神器',
|
||||||
background: '#fe11ff',
|
background: '#fe11ff',
|
||||||
},{
|
},
|
||||||
|
{
|
||||||
value: '传说',
|
value: '传说',
|
||||||
background: '#fc8711',
|
background: '#fc8711',
|
||||||
},{
|
},
|
||||||
|
{
|
||||||
value: '史诗',
|
value: '史诗',
|
||||||
background: '#feca11',
|
background: '#feca11',
|
||||||
},{
|
},
|
||||||
|
{
|
||||||
value: '太初',
|
value: '太初',
|
||||||
background: 'linear-gradient(180deg, #70faa7 0%, #7bfefe 100%)',
|
background: 'linear-gradient(180deg, #70faa7 0%, #7bfefe 100%)',
|
||||||
}]
|
},
|
||||||
|
]
|
||||||
|
|
||||||
const choose = (rarity: string) => {
|
const choose = (rarity: string) => {
|
||||||
if (value.value === rarity) {
|
if (value.value === rarity) {
|
||||||
value.value = undefined
|
value.value = undefined
|
||||||
}
|
} else {
|
||||||
else{
|
|
||||||
value.value = rarity
|
value.value = rarity
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|
||||||
.active {
|
.active {
|
||||||
background: url('@/assets/img/control/item_checked.png') no-repeat center;
|
background: url('@/assets/img/control/item_checked.png') no-repeat center;
|
||||||
background-size: 12px 10px;
|
background-size: 12px 10px;
|
||||||
|
|||||||
@@ -14,7 +14,12 @@
|
|||||||
>
|
>
|
||||||
<!-- 装备图标 装备名称 -->
|
<!-- 装备图标 装备名称 -->
|
||||||
<div class="flex w-full items-center justify-center gap-5px">
|
<div class="flex w-full items-center justify-center gap-5px">
|
||||||
<div><img :src="getImageURL('equipment' + props.suit?.imageUrl.replace('/suit/','/suit/icon/'))" alt="装备图标"></div>
|
<div>
|
||||||
|
<img
|
||||||
|
:src="getImageURL('equipment' + props.suit?.imageUrl.replace('/suit/', '/suit/icon/'))"
|
||||||
|
alt="装备图标"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<div :class="rarity">{{ props.suit?.name }}</div>
|
<div :class="rarity">{{ props.suit?.name }}</div>
|
||||||
<div :class="rarity">{{ props.suit?.point }}点</div>
|
<div :class="rarity">{{ props.suit?.point }}点</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import { h, reactive, renderList } from "vue"
|
import { h, reactive, renderList } from 'vue'
|
||||||
import { createSharedComposable } from "@vueuse/core"
|
import { createSharedComposable } from '@vueuse/core'
|
||||||
import ActionDialog from "@/components/calc/action-dialog/index.vue"
|
import ActionDialog from '@/components/calc/action-dialog/index.vue'
|
||||||
import type { JSX } from "vue/jsx-runtime"
|
import type { JSX } from 'vue/jsx-runtime'
|
||||||
|
|
||||||
export type ConfirmDialogOption = Omit<ShowDialogOption, "okButton" | "cancelButton">
|
export type ConfirmDialogOption = Omit<ShowDialogOption, 'okButton' | 'cancelButton'>
|
||||||
export type AlertDialogOption = Omit<ShowDialogOption, "okButton" | "cancelButton">
|
export type AlertDialogOption = Omit<ShowDialogOption, 'okButton' | 'cancelButton'>
|
||||||
export type ElementLike = JSX.Element | string | ElementLike[]
|
export type ElementLike = JSX.Element | string | ElementLike[]
|
||||||
|
|
||||||
function randomId() {
|
function randomId() {
|
||||||
@@ -54,7 +54,7 @@ export interface ShowDialogOption {
|
|||||||
rejectButton?: string | boolean
|
rejectButton?: string | boolean
|
||||||
|
|
||||||
// 默认状态
|
// 默认状态
|
||||||
defaultStatus?: DialogResult["status"]
|
defaultStatus?: DialogResult['status']
|
||||||
|
|
||||||
mask?: boolean
|
mask?: boolean
|
||||||
|
|
||||||
@@ -70,7 +70,7 @@ export interface DialogInstance {
|
|||||||
|
|
||||||
export interface DialogResult {
|
export interface DialogResult {
|
||||||
id: DialogID
|
id: DialogID
|
||||||
status: "ok" | "reject" | "cancel" | "none"
|
status: 'ok' | 'reject' | 'cancel' | 'none'
|
||||||
data?: any
|
data?: any
|
||||||
readonly isOk: boolean
|
readonly isOk: boolean
|
||||||
readonly isCancel: boolean
|
readonly isCancel: boolean
|
||||||
@@ -87,23 +87,23 @@ export const useDialog = createSharedComposable(() => {
|
|||||||
return id
|
return id
|
||||||
}
|
}
|
||||||
|
|
||||||
function close(id: DialogID, status = "cancel", duration = 400) {
|
function close(id: DialogID, status = 'cancel', duration = 400) {
|
||||||
const dialog = dialogs.get(id)
|
const dialog = dialogs.get(id)
|
||||||
if (!dialog) {
|
if (!dialog) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
dialog.resolve({
|
dialog.resolve({
|
||||||
id,
|
id,
|
||||||
status: "ok",
|
status: 'ok',
|
||||||
get isOk() {
|
get isOk() {
|
||||||
return status == "ok"
|
return status == 'ok'
|
||||||
},
|
},
|
||||||
get isCancel() {
|
get isCancel() {
|
||||||
return status == "cancel"
|
return status == 'cancel'
|
||||||
},
|
},
|
||||||
get isReject() {
|
get isReject() {
|
||||||
return status == "reject"
|
return status == 'reject'
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
dialog.visible = false
|
dialog.visible = false
|
||||||
const fn = () => dialogs.delete(id)
|
const fn = () => dialogs.delete(id)
|
||||||
@@ -115,14 +115,27 @@ export const useDialog = createSharedComposable(() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function render() {
|
function render() {
|
||||||
return renderList(dialogs.values(), e => e.render(e.visible))
|
return renderList(dialogs.values(), (e) => e.render(e.visible))
|
||||||
}
|
}
|
||||||
|
|
||||||
async function show(option: ShowDialogOption = {}) {
|
async function show(option: ShowDialogOption = {}) {
|
||||||
return new Promise<DialogResult>(resolve => {
|
return new Promise<DialogResult>((resolve) => {
|
||||||
const { id = randomId(), header = true, content, action, timeout, okButton = false, cancelButton = false, rejectButton = false, defaultStatus = "none", duration = 400, mask = false, scale = 1.0 } = option
|
const {
|
||||||
|
id = randomId(),
|
||||||
|
header = true,
|
||||||
|
content,
|
||||||
|
action,
|
||||||
|
timeout,
|
||||||
|
okButton = false,
|
||||||
|
cancelButton = false,
|
||||||
|
rejectButton = false,
|
||||||
|
defaultStatus = 'none',
|
||||||
|
duration = 400,
|
||||||
|
mask = false,
|
||||||
|
scale = 1.0,
|
||||||
|
} = option
|
||||||
|
|
||||||
const onClose = (status: DialogResult["status"] = defaultStatus) => {
|
const onClose = (status: DialogResult['status'] = defaultStatus) => {
|
||||||
close(id, status, duration)
|
close(id, status, duration)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,23 +154,30 @@ export const useDialog = createSharedComposable(() => {
|
|||||||
visible,
|
visible,
|
||||||
onClose,
|
onClose,
|
||||||
mask,
|
mask,
|
||||||
scale
|
scale,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
default() {
|
default() {
|
||||||
switch (typeof content) {
|
switch (typeof content) {
|
||||||
case "function":
|
case 'function':
|
||||||
return content()
|
return content()
|
||||||
case "string":
|
case 'string':
|
||||||
return h("div", { class: "w-full justify-center text-hex-d4d6b6 text-center", style: "margin:10px" }, content)
|
return h(
|
||||||
|
'div',
|
||||||
|
{
|
||||||
|
class: 'w-full justify-center text-hex-d4d6b6 text-center',
|
||||||
|
style: 'margin:10px',
|
||||||
|
},
|
||||||
|
content,
|
||||||
|
)
|
||||||
default:
|
default:
|
||||||
return content
|
return content
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
action: typeof action == "function" || !action ? action : () => action
|
action: typeof action == 'function' || !action ? action : () => action,
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
if (timeout) {
|
if (timeout) {
|
||||||
@@ -169,18 +189,18 @@ export const useDialog = createSharedComposable(() => {
|
|||||||
async function alert(option: AlertDialogOption = {}) {
|
async function alert(option: AlertDialogOption = {}) {
|
||||||
return show({
|
return show({
|
||||||
...option,
|
...option,
|
||||||
defaultStatus: "ok",
|
defaultStatus: 'ok',
|
||||||
okButton: true,
|
okButton: true,
|
||||||
cancelButton: false
|
cancelButton: false,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async function confirm(option: ConfirmDialogOption = {}) {
|
async function confirm(option: ConfirmDialogOption = {}) {
|
||||||
return show({
|
return show({
|
||||||
...option,
|
...option,
|
||||||
defaultStatus: "cancel",
|
defaultStatus: 'cancel',
|
||||||
okButton: true,
|
okButton: true,
|
||||||
cancelButton: true
|
cancelButton: true,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
@@ -189,6 +209,6 @@ export const useDialog = createSharedComposable(() => {
|
|||||||
render,
|
render,
|
||||||
show,
|
show,
|
||||||
close,
|
close,
|
||||||
randomId
|
randomId,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import type { Fn } from "@vueuse/core"
|
import type { Fn } from '@vueuse/core'
|
||||||
import type { InjectionKey, Ref } from "vue";
|
import type { InjectionKey, Ref } from 'vue'
|
||||||
import { inject, provide, ref, watch } from "vue"
|
import { inject, provide, ref, watch } from 'vue'
|
||||||
|
|
||||||
const IsOpenSymbol: InjectionKey<Ref<boolean>> = Symbol("is-open")
|
const IsOpenSymbol: InjectionKey<Ref<boolean>> = Symbol('is-open')
|
||||||
|
|
||||||
export function isShow() {
|
export function isShow() {
|
||||||
return inject(IsOpenSymbol, ref(false))
|
return inject(IsOpenSymbol, ref(false))
|
||||||
@@ -15,12 +15,12 @@ interface OnShowOption {
|
|||||||
export function onShow(fn: Fn, { immediate = false }: OnShowOption = {}) {
|
export function onShow(fn: Fn, { immediate = false }: OnShowOption = {}) {
|
||||||
return watch(
|
return watch(
|
||||||
isShow(),
|
isShow(),
|
||||||
val => {
|
(val) => {
|
||||||
if (val) {
|
if (val) {
|
||||||
fn()
|
fn()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ immediate }
|
{ immediate },
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { PropType } from "vue"
|
import type { PropType } from 'vue'
|
||||||
|
|
||||||
export type ClassType = string | string[]
|
export type ClassType = string | string[]
|
||||||
|
|
||||||
@@ -8,4 +8,6 @@ export const valuePropType = [String, Number, Object, Boolean, Array] as PropTyp
|
|||||||
|
|
||||||
export const classPropType = [String, Array] as PropType<string | string[]>
|
export const classPropType = [String, Array] as PropType<string | string[]>
|
||||||
|
|
||||||
export const labelPropType = [String, Function] as PropType<string | ((val?: BaseType) => string) | null>
|
export const labelPropType = [String, Function] as PropType<
|
||||||
|
string | ((val?: BaseType) => string) | null
|
||||||
|
>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import '@/style/index.scss'
|
import '@/style/index.scss'
|
||||||
|
|
||||||
import { createApp } from 'vue'
|
import { createApp } from 'vue'
|
||||||
import { pinia } from "@/stores"
|
import { pinia } from '@/stores'
|
||||||
|
|
||||||
import App from '@/pages/IndexView.vue'
|
import App from '@/pages/IndexView.vue'
|
||||||
|
|
||||||
|
|||||||
@@ -46,7 +46,4 @@ const infoStore = useInfoStore()
|
|||||||
const equTab = ref(0)
|
const equTab = ref(0)
|
||||||
const stoneTab = ref(0)
|
const stoneTab = ref(0)
|
||||||
const anotherTab = ref(0)
|
const anotherTab = ref(0)
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,11 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex flex-wrap gap-4px content-start" :style="{ width: `${rowCount * 32}px` }">
|
<div class="flex flex-wrap gap-4px content-start" :style="{ width: `${rowCount * 32}px` }">
|
||||||
<template v-for="(equ, _) in equs" :key="_">
|
<template v-for="(equ, _) in equs" :key="_">
|
||||||
<EquipmentIcon :equipment="equ" :inactive="configStore.config.equips[equ?.itemDetailType ?? '']?.id != equ?.id" @click="configStore.chooseEqu(equ)"/>
|
<EquipmentIcon
|
||||||
|
:equipment="equ"
|
||||||
|
:inactive="configStore.config.equips[equ?.itemDetailType ?? '']?.id != equ?.id"
|
||||||
|
@click="configStore.chooseEqu(equ)"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -23,9 +27,7 @@ const infoStore = useInfoStore()
|
|||||||
const configStore = useConfigStore()
|
const configStore = useConfigStore()
|
||||||
|
|
||||||
const equs = computed(() => {
|
const equs = computed(() => {
|
||||||
const items = infoStore.equips.filter(
|
const items = infoStore.equips.filter((equip) => ['称号', '宠物'].includes(equip.itemDetailType))
|
||||||
(equip) => ['称号','宠物'].includes(equip.itemDetailType),
|
|
||||||
)
|
|
||||||
const res: (IEquipment | undefined)[] = []
|
const res: (IEquipment | undefined)[] = []
|
||||||
Array.from(new Set(items.map((item) => item.itemDetailType))).forEach((type) => {
|
Array.from(new Set(items.map((item) => item.itemDetailType))).forEach((type) => {
|
||||||
const equList = items.filter((item) => item.itemDetailType === type)
|
const equList = items.filter((item) => item.itemDetailType === type)
|
||||||
@@ -36,17 +38,12 @@ const equs = computed(() => {
|
|||||||
const rarityOrder = ['传说', '神器', '稀有']
|
const rarityOrder = ['传说', '神器', '稀有']
|
||||||
return rarityOrder.indexOf(a.rarity) - rarityOrder.indexOf(b.rarity)
|
return rarityOrder.indexOf(a.rarity) - rarityOrder.indexOf(b.rarity)
|
||||||
})
|
})
|
||||||
res.push(
|
res.push(...equList)
|
||||||
...equList
|
|
||||||
)
|
|
||||||
const remind = rowCount - (res.length % rowCount)
|
const remind = rowCount - (res.length % rowCount)
|
||||||
res.push(...Array(remind + rowCount).fill(undefined))
|
res.push(...Array(remind + rowCount).fill(undefined))
|
||||||
})
|
})
|
||||||
const treasure = infoStore.equips.filter(
|
const treasure = infoStore.equips.filter((equip) => equip.categorize.includes('秘宝'))
|
||||||
(equip) => equip.categorize.includes('秘宝'),
|
|
||||||
)
|
|
||||||
res.push(...treasure, ...Array(rowCount - treasure.length).fill(undefined))
|
res.push(...treasure, ...Array(rowCount - treasure.length).fill(undefined))
|
||||||
return res
|
return res
|
||||||
})
|
})
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -24,7 +24,11 @@
|
|||||||
<div class="flex flex-wrap gap-4px content-start" :style="{ width: `${rowCount * 32}px` }">
|
<div class="flex flex-wrap gap-4px content-start" :style="{ width: `${rowCount * 32}px` }">
|
||||||
<template v-for="(equip, _) in suitEquipments" :key="_">
|
<template v-for="(equip, _) in suitEquipments" :key="_">
|
||||||
<template v-if="equip?.rarity == curRarity || !curRarity">
|
<template v-if="equip?.rarity == curRarity || !curRarity">
|
||||||
<EquipmentIcon :equipment="equip" :inactive="configStore.config.equips[equip?.itemDetailType ?? '']?.fusion != equip?.id" @click="configStore.chooseEqu(equip,true)"/>
|
<EquipmentIcon
|
||||||
|
:equipment="equip"
|
||||||
|
:inactive="configStore.config.equips[equip?.itemDetailType ?? '']?.fusion != equip?.id"
|
||||||
|
@click="configStore.chooseEqu(equip, true)"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template v-else>
|
<template v-else>
|
||||||
@@ -64,7 +68,9 @@ const suits = computed(() => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const suitEquipments = computed(() => {
|
const suitEquipments = computed(() => {
|
||||||
const equs = infoStore.stones.filter((a) => a.suit.includes(curSuit.value.toString()) && a.suit.length === 1 )
|
const equs = infoStore.stones.filter(
|
||||||
|
(a) => a.suit.includes(curSuit.value.toString()) && a.suit.length === 1,
|
||||||
|
)
|
||||||
|
|
||||||
const res: (IEquipment | undefined)[] = []
|
const res: (IEquipment | undefined)[] = []
|
||||||
const raritiyList = ['神器', '传说', '史诗']
|
const raritiyList = ['神器', '传说', '史诗']
|
||||||
@@ -73,21 +79,19 @@ const suitEquipments = computed(() => {
|
|||||||
const equ: (IEquipment | undefined)[] = equs.filter((a) => a.rarity === rarity)
|
const equ: (IEquipment | undefined)[] = equs.filter((a) => a.rarity === rarity)
|
||||||
equ.splice(5, 0, undefined)
|
equ.splice(5, 0, undefined)
|
||||||
equ.splice(9, 0, undefined)
|
equ.splice(9, 0, undefined)
|
||||||
res.push(
|
res.push(...equ, ...Array(Math.max(0, rowCount - equ.length)).fill(undefined))
|
||||||
...equ,
|
|
||||||
...Array(Math.max(0,rowCount - equ.length)).fill(undefined),
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
return res
|
return res
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
const handleDoubleClick = () => {
|
const handleDoubleClick = () => {
|
||||||
if (!curRarity.value) return
|
if (!curRarity.value) return
|
||||||
if (curRarity.value == '太初') return
|
if (curRarity.value == '太初') return
|
||||||
suitEquipments.value.filter(a=>!!a && a.rarity == curRarity.value).splice(0,11).forEach((a) => {
|
suitEquipments.value
|
||||||
|
.filter((a) => !!a && a.rarity == curRarity.value)
|
||||||
|
.splice(0, 11)
|
||||||
|
.forEach((a) => {
|
||||||
configStore.chooseEqu(a, true)
|
configStore.chooseEqu(a, true)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -3,7 +3,11 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex flex-wrap gap-4px content-start" :style="{ width: `${rowCount * 32}px` }">
|
<div class="flex flex-wrap gap-4px content-start" :style="{ width: `${rowCount * 32}px` }">
|
||||||
<template v-for="(equip, _) in equs" :key="_">
|
<template v-for="(equip, _) in equs" :key="_">
|
||||||
<EquipmentIcon :inactive="configStore.config.equips[equip?.itemDetailType ?? '']?.fusion != equip?.id" :equipment="equip" @click="configStore.chooseEqu(equip,true)" />
|
<EquipmentIcon
|
||||||
|
:inactive="configStore.config.equips[equip?.itemDetailType ?? '']?.fusion != equip?.id"
|
||||||
|
:equipment="equip"
|
||||||
|
@click="configStore.chooseEqu(equip, true)"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -23,23 +27,21 @@ const infoStore = useInfoStore()
|
|||||||
const configStore = useConfigStore()
|
const configStore = useConfigStore()
|
||||||
|
|
||||||
const equs = computed(() => {
|
const equs = computed(() => {
|
||||||
const items = infoStore.stones.filter(
|
const items = infoStore.stones.filter((equip) => equip.categorize.includes('神界'))
|
||||||
(equip) => equip.categorize.includes('神界'),
|
|
||||||
)
|
|
||||||
const res: (IEquipment | undefined)[] = []
|
const res: (IEquipment | undefined)[] = []
|
||||||
res.push(
|
res.push(
|
||||||
...items.filter((a) => a.rarity === '太初'),
|
...items.filter((a) => a.rarity === '太初'),
|
||||||
...Array(Math.max(0,rowCount - items.filter((a) => a.rarity === '太初').length)).fill(undefined),
|
...Array(Math.max(0, rowCount - items.filter((a) => a.rarity === '太初').length)).fill(
|
||||||
);
|
undefined,
|
||||||
|
),
|
||||||
['手镯','项链','戒指','','辅助装备','魔法石','耳环',''].forEach((cat) => {
|
|
||||||
const equ: (IEquipment | undefined)[] = items.filter((a) => a.rarity === '史诗' && a.itemDetailType == cat)
|
|
||||||
res.push(
|
|
||||||
...equ,
|
|
||||||
...Array(Math.max(0, 7 - equ.length)).fill(undefined),
|
|
||||||
)
|
)
|
||||||
})
|
|
||||||
|
|
||||||
|
;['手镯', '项链', '戒指', '', '辅助装备', '魔法石', '耳环', ''].forEach((cat) => {
|
||||||
|
const equ: (IEquipment | undefined)[] = items.filter(
|
||||||
|
(a) => a.rarity === '史诗' && a.itemDetailType == cat,
|
||||||
|
)
|
||||||
|
res.push(...equ, ...Array(Math.max(0, 7 - equ.length)).fill(undefined))
|
||||||
|
})
|
||||||
|
|
||||||
// const categorize = Array.from(new Set(items.map((item) => item.categorize)))
|
// const categorize = Array.from(new Set(items.map((item) => item.categorize)))
|
||||||
// raritiyList.forEach((rarity) => {
|
// raritiyList.forEach((rarity) => {
|
||||||
|
|||||||
@@ -3,7 +3,11 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex flex-wrap gap-4px content-start" :style="{ width: `${rowCount * 32}px` }">
|
<div class="flex flex-wrap gap-4px content-start" :style="{ width: `${rowCount * 32}px` }">
|
||||||
<template v-for="(equip, _) in equs" :key="_">
|
<template v-for="(equip, _) in equs" :key="_">
|
||||||
<EquipmentIcon :inactive="configStore.config.equips[equip?.itemDetailType ?? '']?.fusion != equip?.id" :equipment="equip" @click="configStore.chooseEqu(equip,true)" />
|
<EquipmentIcon
|
||||||
|
:inactive="configStore.config.equips[equip?.itemDetailType ?? '']?.fusion != equip?.id"
|
||||||
|
:equipment="equip"
|
||||||
|
@click="configStore.chooseEqu(equip, true)"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -23,20 +27,17 @@ const infoStore = useInfoStore()
|
|||||||
const configStore = useConfigStore()
|
const configStore = useConfigStore()
|
||||||
|
|
||||||
const equs = computed(() => {
|
const equs = computed(() => {
|
||||||
const items = infoStore.stones.filter(
|
const items = infoStore.stones.filter((equip) => equip.categorize.includes('通宝'))
|
||||||
(equip) => equip.categorize.includes('通宝'),
|
|
||||||
)
|
|
||||||
const res: (IEquipment | undefined)[] = []
|
const res: (IEquipment | undefined)[] = []
|
||||||
const raritiyList = ['神器', '史诗']
|
const raritiyList = ['神器', '史诗']
|
||||||
const categorize = Array.from(new Set(items.map((item) => item.categorize)))
|
const categorize = Array.from(new Set(items.map((item) => item.categorize)))
|
||||||
raritiyList.forEach((rarity) => {
|
raritiyList.forEach((rarity) => {
|
||||||
categorize.forEach((cat) => {
|
categorize.forEach((cat) => {
|
||||||
const equ : (IEquipment | undefined)[] = items.filter((a) => a.rarity === rarity && a.categorize === cat)
|
const equ: (IEquipment | undefined)[] = items.filter(
|
||||||
equ.splice(5,0,undefined)
|
(a) => a.rarity === rarity && a.categorize === cat,
|
||||||
res.push(
|
|
||||||
...equ,
|
|
||||||
...Array(Math.max(0,rowCount - equ.length)).fill(undefined),
|
|
||||||
)
|
)
|
||||||
|
equ.splice(5, 0, undefined)
|
||||||
|
res.push(...equ, ...Array(Math.max(0, rowCount - equ.length)).fill(undefined))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
return res
|
return res
|
||||||
|
|||||||
@@ -3,7 +3,11 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex flex-wrap gap-4px content-start" :style="{ width: `${rowCount * 32}px` }">
|
<div class="flex flex-wrap gap-4px content-start" :style="{ width: `${rowCount * 32}px` }">
|
||||||
<template v-for="(weapon, _) in weapons" :key="_">
|
<template v-for="(weapon, _) in weapons" :key="_">
|
||||||
<EquipmentIcon :equipment="weapon" :inactive="configStore.config.equips['副武器']?.id != weapon?.id" @click="configStore.chooseEqu(weapon,false,true)"/>
|
<EquipmentIcon
|
||||||
|
:equipment="weapon"
|
||||||
|
:inactive="configStore.config.equips['副武器']?.id != weapon?.id"
|
||||||
|
@click="configStore.chooseEqu(weapon, false, true)"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -40,5 +44,4 @@ const weapons = computed(() => {
|
|||||||
})
|
})
|
||||||
return res
|
return res
|
||||||
})
|
})
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -24,7 +24,11 @@
|
|||||||
<div class="flex flex-wrap gap-4px content-start" :style="{ width: `${rowCount * 32}px` }">
|
<div class="flex flex-wrap gap-4px content-start" :style="{ width: `${rowCount * 32}px` }">
|
||||||
<template v-for="(equip, _) in suitEquipments" :key="_">
|
<template v-for="(equip, _) in suitEquipments" :key="_">
|
||||||
<template v-if="equip?.rarity == curRarity || !curRarity">
|
<template v-if="equip?.rarity == curRarity || !curRarity">
|
||||||
<EquipmentIcon :equipment="equip" :inactive="configStore.config.equips[equip?.itemDetailType ?? '']?.id != equip?.id" @click="configStore.chooseEqu(equip)"/>
|
<EquipmentIcon
|
||||||
|
:equipment="equip"
|
||||||
|
:inactive="configStore.config.equips[equip?.itemDetailType ?? '']?.id != equip?.id"
|
||||||
|
@click="configStore.chooseEqu(equip)"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template v-else>
|
<template v-else>
|
||||||
@@ -64,30 +68,44 @@ const suits = computed(() => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const suitEquipments = computed(() => {
|
const suitEquipments = computed(() => {
|
||||||
const equs = infoStore.equips.filter((a) => a.suit.includes(curSuit.value.toString()) && a.suit.length === 1 )
|
const equs = infoStore.equips.filter(
|
||||||
|
(a) => a.suit.includes(curSuit.value.toString()) && a.suit.length === 1,
|
||||||
|
)
|
||||||
|
|
||||||
const res: (IEquipment | undefined)[] = []
|
const res: (IEquipment | undefined)[] = []
|
||||||
const raritiyList = ['神器', '传说', '史诗']
|
const raritiyList = ['神器', '传说', '史诗']
|
||||||
raritiyList.forEach((rarity) => {
|
raritiyList.forEach((rarity) => {
|
||||||
const equ : (IEquipment | undefined)[] = equs.filter((a) => a.rarity === rarity && !a.name.includes('黑牙'))
|
const equ: (IEquipment | undefined)[] = equs.filter(
|
||||||
|
(a) => a.rarity === rarity && !a.name.includes('黑牙'),
|
||||||
|
)
|
||||||
equ.splice(5, 0, undefined)
|
equ.splice(5, 0, undefined)
|
||||||
equ.splice(9, 0, undefined)
|
equ.splice(9, 0, undefined)
|
||||||
res.push(
|
res.push(...equ, ...Array(Math.max(0, rowCount - equ.length)).fill(undefined))
|
||||||
...equ,
|
|
||||||
...Array(Math.max(0,rowCount - equ.length)).fill(undefined),
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
const remind = equs.filter(a=>a.rarity == '太初' || a.name.includes('黑牙')).sort((a,b)=>(a.rarity == '太初' ? 1 : 0) - (b.rarity == '太初' ? 1 : 0))
|
const remind = equs
|
||||||
res.push(undefined,undefined,...remind.filter(a=>a.itemDetailType == '项链'),undefined,...remind.filter(a=>a.itemDetailType == '手镯'),undefined,...remind.filter(a=>a.itemDetailType == '戒指'),...Array(Math.max(0,rowCount - remind.length -4)).fill(undefined))
|
.filter((a) => a.rarity == '太初' || a.name.includes('黑牙'))
|
||||||
|
.sort((a, b) => (a.rarity == '太初' ? 1 : 0) - (b.rarity == '太初' ? 1 : 0))
|
||||||
|
res.push(
|
||||||
|
undefined,
|
||||||
|
undefined,
|
||||||
|
...remind.filter((a) => a.itemDetailType == '项链'),
|
||||||
|
undefined,
|
||||||
|
...remind.filter((a) => a.itemDetailType == '手镯'),
|
||||||
|
undefined,
|
||||||
|
...remind.filter((a) => a.itemDetailType == '戒指'),
|
||||||
|
...Array(Math.max(0, rowCount - remind.length - 4)).fill(undefined),
|
||||||
|
)
|
||||||
return res
|
return res
|
||||||
})
|
})
|
||||||
|
|
||||||
const handleDoubleClick = () => {
|
const handleDoubleClick = () => {
|
||||||
if (!curRarity.value) return
|
if (!curRarity.value) return
|
||||||
if (curRarity.value == '太初') return
|
if (curRarity.value == '太初') return
|
||||||
suitEquipments.value.filter(a=>!!a && a.rarity == curRarity.value).splice(0,11).forEach((a) => {
|
suitEquipments.value
|
||||||
|
.filter((a) => !!a && a.rarity == curRarity.value)
|
||||||
|
.splice(0, 11)
|
||||||
|
.forEach((a) => {
|
||||||
configStore.chooseEqu(a)
|
configStore.chooseEqu(a)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -3,7 +3,11 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex flex-wrap gap-4px content-start" :style="{ width: `${rowCount * 32}px` }">
|
<div class="flex flex-wrap gap-4px content-start" :style="{ width: `${rowCount * 32}px` }">
|
||||||
<template v-for="(equip, _) in equs" :key="_">
|
<template v-for="(equip, _) in equs" :key="_">
|
||||||
<EquipmentIcon :inactive="configStore.config.equips[equip?.itemDetailType ?? '']?.id != equip?.id" :equipment="equip" @click="configStore.chooseEqu(equip)" />
|
<EquipmentIcon
|
||||||
|
:inactive="configStore.config.equips[equip?.itemDetailType ?? '']?.id != equip?.id"
|
||||||
|
:equipment="equip"
|
||||||
|
@click="configStore.chooseEqu(equip)"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -32,10 +36,7 @@ const equs = computed(() => {
|
|||||||
const equ: (IEquipment | undefined)[] = items.filter((a) => a.rarity === rarity)
|
const equ: (IEquipment | undefined)[] = items.filter((a) => a.rarity === rarity)
|
||||||
equ.splice(5, 0, undefined)
|
equ.splice(5, 0, undefined)
|
||||||
equ.splice(9, 0, undefined)
|
equ.splice(9, 0, undefined)
|
||||||
res.push(
|
res.push(...equ, ...Array(Math.max(0, rowCount - equ.length)).fill(undefined))
|
||||||
...equ,
|
|
||||||
...Array(Math.max(0,rowCount - equ.length)).fill(undefined),
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
return res
|
return res
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -3,7 +3,11 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex flex-wrap gap-4px content-start" :style="{ width: `${rowCount * 32}px` }">
|
<div class="flex flex-wrap gap-4px content-start" :style="{ width: `${rowCount * 32}px` }">
|
||||||
<template v-for="(weapon, _) in weapons" :key="_">
|
<template v-for="(weapon, _) in weapons" :key="_">
|
||||||
<EquipmentIcon :equipment="weapon" :inactive="configStore.config.equips['武器']?.id != weapon?.id" @click="configStore.chooseEqu(weapon)"/>
|
<EquipmentIcon
|
||||||
|
:equipment="weapon"
|
||||||
|
:inactive="configStore.config.equips['武器']?.id != weapon?.id"
|
||||||
|
@click="configStore.chooseEqu(weapon)"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -39,5 +43,4 @@ const weapons = computed(() => {
|
|||||||
})
|
})
|
||||||
return res
|
return res
|
||||||
})
|
})
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="w-340px bg-black flex flex-col h-90vh">
|
<div class="w-340px bg-black flex flex-col h-90vh">
|
||||||
|
<calc-dialog lazy header="装备条件" v-model:visible="triggerVisible">
|
||||||
|
<options />
|
||||||
|
</calc-dialog>
|
||||||
<!-- 头部 选择是装备还是融合石 -->
|
<!-- 头部 选择是装备还是融合石 -->
|
||||||
<div class="flex bg-#101012 h-40px text-#6C5E4A font-bold">
|
<div class="flex bg-#101012 h-40px text-#6C5E4A font-bold">
|
||||||
<div
|
<div
|
||||||
@@ -30,7 +33,7 @@
|
|||||||
品质:<EquipmentRaritySelect v-model="curRarity" />
|
品质:<EquipmentRaritySelect v-model="curRarity" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-1 items-center">
|
<div class="flex flex-1 items-center justify-between">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
套装:
|
套装:
|
||||||
<div class="flex items-center justify-center gap-2px">
|
<div class="flex items-center justify-center gap-2px">
|
||||||
@@ -47,6 +50,11 @@
|
|||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<calc-button
|
||||||
|
icon="set"
|
||||||
|
title="装备触发条件"
|
||||||
|
@click="triggerVisible = !triggerVisible"
|
||||||
|
></calc-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="overflow-y-auto gap-1 p-1 flex flex-col items-center flex-1 h-0">
|
<div class="overflow-y-auto gap-1 p-1 flex flex-col items-center flex-1 h-0">
|
||||||
@@ -55,18 +63,14 @@
|
|||||||
<div class="item-head w-full">{{ item.name }}</div>
|
<div class="item-head w-full">{{ item.name }}</div>
|
||||||
<div class="flex flex-wrap gap-4px justify-around w-full">
|
<div class="flex flex-wrap gap-4px justify-around w-full">
|
||||||
<template v-for="(equ, _) in item.equs" :key="_">
|
<template v-for="(equ, _) in item.equs" :key="_">
|
||||||
<EquipmentIcon
|
<EquipmentIcon :inactive="!isActive(equ)" :equipment="equ" @click="chooseEqu(equ)" />
|
||||||
:inactive="!isActive(equ)"
|
|
||||||
:equipment="equ"
|
|
||||||
@click="chooseEqu(equ)"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="px-5px flex flex-col">
|
<div class="px-5px flex flex-col h-90vh">
|
||||||
<div class="flex flex-col overflow-hidden bg-black" v-if="curEquInfo">
|
<div class="flex flex-col overflow-hidden bg-black" v-if="curEquInfo">
|
||||||
<div class="item-head">基础信息</div>
|
<div class="item-head">基础信息</div>
|
||||||
<div class="flex-1 overflow-y-auto overflow-x-hidden bg-black w-240px">
|
<div class="flex-1 overflow-y-auto overflow-x-hidden bg-black w-240px">
|
||||||
@@ -127,6 +131,11 @@ import EquipmentIcon from '@/components/dnf/Equipment/Icon/index.vue'
|
|||||||
import Info from '@/components/dnf/Equipment/Info/index.vue'
|
import Info from '@/components/dnf/Equipment/Info/index.vue'
|
||||||
import SuitInfo from '@/components/dnf/Equipment/SuitInfo/index.vue'
|
import SuitInfo from '@/components/dnf/Equipment/SuitInfo/index.vue'
|
||||||
import { formatEqu, formatStone } from './formatData'
|
import { formatEqu, formatStone } from './formatData'
|
||||||
|
import options from './components/options.vue'
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
alter: string
|
||||||
|
}>()
|
||||||
|
|
||||||
const infoStore = useInfoStore()
|
const infoStore = useInfoStore()
|
||||||
const type = ref('equ')
|
const type = ref('equ')
|
||||||
@@ -137,6 +146,7 @@ const curSuitLv = ref({
|
|||||||
rarity: '史诗',
|
rarity: '史诗',
|
||||||
lv: 1,
|
lv: 1,
|
||||||
})
|
})
|
||||||
|
const triggerVisible = ref(false)
|
||||||
|
|
||||||
const raritiyList = ['稀有', '神器', '传说', '史诗', '太初']
|
const raritiyList = ['稀有', '神器', '传说', '史诗', '太初']
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
<template>
|
||||||
|
<div class="flex flex-col gap-2 w-250px p-2">
|
||||||
|
<div v-for="option in info.options" :key="option.id" class="flex items-center gap-2">
|
||||||
|
<div class="w-60px text-end">{{ option.name }}</div>
|
||||||
|
<calc-select class="flex-1 !h-20px" :appendTo="dialogRef" v-model="config.config.options[option.id.toString()]">
|
||||||
|
<calc-option v-for="(item, index) in option.options" :key="index" :value="index">
|
||||||
|
{{ item }}
|
||||||
|
</calc-option>
|
||||||
|
</calc-select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { useConfigStore, useInfoStore } from '@/stores'
|
||||||
|
const dialogRef = inject("dialogRef", ref(null))
|
||||||
|
const config = useConfigStore()
|
||||||
|
const info = useInfoStore()
|
||||||
|
</script>
|
||||||
@@ -1,9 +1,8 @@
|
|||||||
import type { IEquipment } from "@/api/info/type"
|
import type { IEquipment } from '@/api/info/type'
|
||||||
|
|
||||||
export const rowCount = 10
|
export const rowCount = 10
|
||||||
|
|
||||||
export const formatEqu = (total: IEquipment[],subweapons?:string[],curSuit
|
export const formatEqu = (total: IEquipment[], subweapons?: string[], curSuit?: string) => {
|
||||||
?:string) => {
|
|
||||||
// 武器
|
// 武器
|
||||||
const item_weapon = total.filter((a) => a.itemType == '武器') ?? []
|
const item_weapon = total.filter((a) => a.itemType == '武器') ?? []
|
||||||
const weapons: (IEquipment | undefined)[] = []
|
const weapons: (IEquipment | undefined)[] = []
|
||||||
@@ -25,14 +24,14 @@ export const formatEqu = (total: IEquipment[],subweapons?:string[],curSuit
|
|||||||
|
|
||||||
// # region 副武器
|
// # region 副武器
|
||||||
const subWeapons: (IEquipment | undefined)[] = []
|
const subWeapons: (IEquipment | undefined)[] = []
|
||||||
const item_sub_weapon = (
|
const item_sub_weapon = (total.filter((a) => subweapons?.includes(a.itemDetailType)) ?? []).sort(
|
||||||
total.filter((a) => subweapons?.includes(a.itemDetailType)) ?? []
|
(a, b) => {
|
||||||
).sort((a, b) => {
|
|
||||||
if (a.categorize == b.categorize) {
|
if (a.categorize == b.categorize) {
|
||||||
return a.itemDetailType.localeCompare(b.itemDetailType)
|
return a.itemDetailType.localeCompare(b.itemDetailType)
|
||||||
}
|
}
|
||||||
return b.categorize.localeCompare(a.categorize)
|
return b.categorize.localeCompare(a.categorize)
|
||||||
})
|
},
|
||||||
|
)
|
||||||
if (item_sub_weapon.length > 0) {
|
if (item_sub_weapon.length > 0) {
|
||||||
subWeapons.push(
|
subWeapons.push(
|
||||||
...item_sub_weapon.map((a) => ({ ...a, itemType: '副武器' })),
|
...item_sub_weapon.map((a) => ({ ...a, itemType: '副武器' })),
|
||||||
|
|||||||
@@ -113,9 +113,13 @@ export default defineComponent({
|
|||||||
<div class="row-name">属性</div>
|
<div class="row-name">属性</div>
|
||||||
<calc-select v-model={option.value} class="flex-1 !h-20px">
|
<calc-select v-model={option.value} class="flex-1 !h-20px">
|
||||||
<calc-option value={0}>无</calc-option>
|
<calc-option value={0}>无</calc-option>
|
||||||
{renderList(basicInfoStore.avatars[part.value].find(a=>a.id == id.value)?.options ?? [], (item) => (
|
{renderList(
|
||||||
|
basicInfoStore.avatars[part.value].find((a) => a.id == id.value)?.options ??
|
||||||
|
[],
|
||||||
|
(item) => (
|
||||||
<calc-option value={item}>{item}</calc-option>
|
<calc-option value={item}>{item}</calc-option>
|
||||||
))}
|
),
|
||||||
|
)}
|
||||||
</calc-select>
|
</calc-select>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -16,7 +16,11 @@
|
|||||||
:step="Number(currentJade(configStore.config.jades[key].id)?.pre)"
|
:step="Number(currentJade(configStore.config.jades[key].id)?.pre)"
|
||||||
></calc-slider> -->
|
></calc-slider> -->
|
||||||
<calc-select class="flex-1 !h-20px" v-model="configStore.config.jades[key].value">
|
<calc-select class="flex-1 !h-20px" v-model="configStore.config.jades[key].value">
|
||||||
<calc-option v-for="(item, index) in valueList(configStore.config.jades[key].id)" :key="item.id" :value="item.id">
|
<calc-option
|
||||||
|
v-for="(item, index) in valueList(configStore.config.jades[key].id)"
|
||||||
|
:key="item.id"
|
||||||
|
:value="item.id"
|
||||||
|
>
|
||||||
{{ item.value }}
|
{{ item.value }}
|
||||||
</calc-option>
|
</calc-option>
|
||||||
</calc-select>
|
</calc-select>
|
||||||
@@ -40,7 +44,7 @@ const currentJade = computed(() => {
|
|||||||
return undefined
|
return undefined
|
||||||
} else {
|
} else {
|
||||||
const res = []
|
const res = []
|
||||||
const cur = infoStore.jades?.find(e => e.id == id) as IJade
|
const cur = infoStore.jades?.find((e) => e.id == id) as IJade
|
||||||
return cur
|
return cur
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -61,21 +65,21 @@ const valueList = computed(() => {
|
|||||||
return undefined
|
return undefined
|
||||||
} else {
|
} else {
|
||||||
const res = []
|
const res = []
|
||||||
const cur = infoStore.jades?.find(e => e.id == id) as IJade
|
const cur = infoStore.jades?.find((e) => e.id == id) as IJade
|
||||||
if (cur) {
|
if (cur) {
|
||||||
const { max, min, unit, pre } = cur
|
const { max, min, unit, pre } = cur
|
||||||
//
|
//
|
||||||
if (unit.includes('等级')) {
|
if (unit.includes('等级')) {
|
||||||
res.push({
|
res.push({
|
||||||
id: 1,
|
id: 1,
|
||||||
value: unit
|
value: unit,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
for (let i = Number(max) as number; i >= Number(min); ) {
|
for (let i = Number(max) as number; i >= Number(min); ) {
|
||||||
if (i != 0) {
|
if (i != 0) {
|
||||||
res.push({
|
res.push({
|
||||||
id: i,
|
id: i,
|
||||||
value: (i > 0 ? "+" : "") + getFloat(i, 1) + unit
|
value: (i > 0 ? '+' : '') + getFloat(i, 1) + unit,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
i = Number((i - Number(pre)).toFixed(1))
|
i = Number((i - Number(pre)).toFixed(1))
|
||||||
|
|||||||
@@ -18,9 +18,9 @@
|
|||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import equipment from './components/Equipments.vue'
|
import equipment from './components/Equipments.vue'
|
||||||
import clothes from './components/Avatars.vue';
|
import clothes from './components/Avatars.vue'
|
||||||
import jade from './components/Jades.vue';
|
import jade from './components/Jades.vue'
|
||||||
import sundry from './components/Sundry.vue';
|
import sundry from './components/Sundry.vue'
|
||||||
const partTab = ref(0)
|
const partTab = ref(0)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -11,8 +11,17 @@
|
|||||||
:equs="configStore.config.equips"
|
:equs="configStore.config.equips"
|
||||||
></Info>
|
></Info>
|
||||||
</div>
|
</div>
|
||||||
<Skill v-if="!configStore.result.state.buffer" :data="configStore.result.state.skills" :standard="infoStore.standard"></Skill>
|
<Skill
|
||||||
<BufferSkill v-else :data="configStore.result.state.skills" :stadard="infoStore.standard" :standard="infoStore.standard"></BufferSkill>
|
v-if="!configStore.result.state.buffer"
|
||||||
|
:data="configStore.result.state.skills"
|
||||||
|
:standard="infoStore.standard"
|
||||||
|
></Skill>
|
||||||
|
<BufferSkill
|
||||||
|
v-else
|
||||||
|
:data="configStore.result.state.skills"
|
||||||
|
:stadard="infoStore.standard"
|
||||||
|
:standard="infoStore.standard"
|
||||||
|
></BufferSkill>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@@ -33,7 +33,9 @@
|
|||||||
</div>
|
</div>
|
||||||
<div>{{ skill.name }}</div>
|
<div>{{ skill.name }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="w-50px flex items-center justify-center">{{ typeof skill.cd === 'number' ? `${skill.cd.toFixed(1)}s` : '-' }}</div>
|
<div class="w-50px flex items-center justify-center">
|
||||||
|
{{ typeof skill.cd === 'number' ? `${skill.cd.toFixed(1)}s` : '-' }}
|
||||||
|
</div>
|
||||||
<component :is="formatDamage(skill)"></component>
|
<component :is="formatDamage(skill)"></component>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -149,7 +151,8 @@ const formatDamage = (skill: IResultSkill) => {
|
|||||||
'div',
|
'div',
|
||||||
{
|
{
|
||||||
class: 'flex items-center justify-center',
|
class: 'flex items-center justify-center',
|
||||||
},[0, 1, 2, 3].map((index) => {
|
},
|
||||||
|
[0, 1, 2, 3].map((index) => {
|
||||||
const value = skill.buff?.[index] - standardSkill.buff?.[index]
|
const value = skill.buff?.[index] - standardSkill.buff?.[index]
|
||||||
return h(
|
return h(
|
||||||
'div',
|
'div',
|
||||||
@@ -162,17 +165,21 @@ const formatDamage = (skill: IResultSkill) => {
|
|||||||
color: value >= 0 ? '#37fa38' : '#ff0000',
|
color: value >= 0 ? '#37fa38' : '#ff0000',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
`${value >= 0 ? '+':''}${index == 3
|
`${value >= 0 ? '+' : ''}${
|
||||||
|
index == 3
|
||||||
? `${Math.round(value).toLocaleString()}%`
|
? `${Math.round(value).toLocaleString()}%`
|
||||||
: Math.round(value).toLocaleString()}`
|
: Math.round(value).toLocaleString()
|
||||||
|
}`,
|
||||||
|
)
|
||||||
|
}),
|
||||||
)
|
)
|
||||||
}))
|
|
||||||
} else {
|
} else {
|
||||||
return h(
|
return h(
|
||||||
'div',
|
'div',
|
||||||
{
|
{
|
||||||
class: 'flex items-center justify-center',
|
class: 'flex items-center justify-center',
|
||||||
},[0, 1, 2, 3].map((index) => {
|
},
|
||||||
|
[0, 1, 2, 3].map((index) => {
|
||||||
const value = skill.buff?.[index]
|
const value = skill.buff?.[index]
|
||||||
return h(
|
return h(
|
||||||
'div',
|
'div',
|
||||||
@@ -188,7 +195,8 @@ const formatDamage = (skill: IResultSkill) => {
|
|||||||
? `${Math.round(value).toLocaleString()}%`
|
? `${Math.round(value).toLocaleString()}%`
|
||||||
: Math.round(value).toLocaleString(),
|
: Math.round(value).toLocaleString(),
|
||||||
)
|
)
|
||||||
}))
|
}),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -44,7 +44,12 @@
|
|||||||
<component :is="formatDamage(skill)"></component>
|
<component :is="formatDamage(skill)"></component>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="!totalStandard" class="h-40px flex items-center justify-center text-18px border-t-1px border-t-solid border-t-#FFFF/15">{{showTotal.toFixed(0)}}</div>
|
<div
|
||||||
|
v-if="!totalStandard"
|
||||||
|
class="h-40px flex items-center justify-center text-18px border-t-1px border-t-solid border-t-#FFFF/15"
|
||||||
|
>
|
||||||
|
{{ showTotal.toFixed(0) }}
|
||||||
|
</div>
|
||||||
<div
|
<div
|
||||||
v-else
|
v-else
|
||||||
class="h-40px flex items-center justify-center text-18px border-t-1px border-t-solid border-t-#FFFF/15"
|
class="h-40px flex items-center justify-center text-18px border-t-1px border-t-solid border-t-#FFFF/15"
|
||||||
@@ -152,7 +157,7 @@ const totalStandard = computed(() => {
|
|||||||
|
|
||||||
const showTotal = computed(() => {
|
const showTotal = computed(() => {
|
||||||
if (!totalStandard.value || totalStandard.value == 0) return totalDamage.value
|
if (!totalStandard.value || totalStandard.value == 0) return totalDamage.value
|
||||||
return (totalDamage.value - totalStandard.value) / totalStandard.value * 100
|
return ((totalDamage.value - totalStandard.value) / totalStandard.value) * 100
|
||||||
})
|
})
|
||||||
|
|
||||||
const formatDamage = (skill: IResultSkill) => {
|
const formatDamage = (skill: IResultSkill) => {
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ export default defineComponent({
|
|||||||
<div
|
<div
|
||||||
class={[
|
class={[
|
||||||
'w-36px absolute h-48px flex flex-col box-border items-center py-3px z-2',
|
'w-36px absolute h-48px flex flex-col box-border items-center py-3px z-2',
|
||||||
(skill.learnLv == 100 && skill.bind) ? '' : 'skill',
|
skill.learnLv == 100 && skill.bind ? '' : 'skill',
|
||||||
]}
|
]}
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
|
|||||||
@@ -10,7 +10,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.passive {
|
.passive {
|
||||||
filter: grayscale(100%) invert(3%) sepia(14%) saturate(874%) hue-rotate(65deg) brightness(105%) contrast(102%);
|
filter: grayscale(100%) invert(3%) sepia(14%) saturate(874%) hue-rotate(65deg) brightness(105%)
|
||||||
|
contrast(102%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.skill {
|
.skill {
|
||||||
|
|||||||
@@ -1,12 +1,15 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<div class="h-90vh w-auto overflow-y-auto overflow-x-hidden">
|
<div class="h-90vh w-auto overflow-y-auto overflow-x-hidden">
|
||||||
<SkillTree :skills="infoStore.skills" v-model:lvInfo="configStore.config.skills" v-model:bindAwake="configStore.config.bindAwake"></SkillTree>
|
<SkillTree
|
||||||
|
:skills="infoStore.skills"
|
||||||
|
v-model:lvInfo="configStore.config.skills"
|
||||||
|
v-model:bindAwake="configStore.config.bindAwake"
|
||||||
|
></SkillTree>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
||||||
<script lang="ts" setup name="Index">
|
<script lang="ts" setup name="Index">
|
||||||
import { useInfoStore } from '@/stores/info'
|
import { useInfoStore } from '@/stores/info'
|
||||||
import SkillTree from './components/SkillTree/index'
|
import SkillTree from './components/SkillTree/index'
|
||||||
|
|||||||
@@ -18,18 +18,17 @@ export default defineComponent(async () => {
|
|||||||
function choose_job(child: IAlterInfo) {
|
function choose_job(child: IAlterInfo) {
|
||||||
return async () => {
|
return async () => {
|
||||||
if (child.comment == '首页') {
|
if (child.comment == '首页') {
|
||||||
return window.open("https://dnftools.com","_blank")
|
return window.open('https://dnftools.com', '_blank')
|
||||||
}
|
}
|
||||||
if (child.name == 'sponsor') {
|
if (child.name == 'sponsor') {
|
||||||
return window.open((child.url ?? ''),"_blank")
|
return window.open(child.url ?? '', '_blank')
|
||||||
}
|
}
|
||||||
if (child.open) {
|
if (child.open) {
|
||||||
const options = child.options ?? []
|
const options = child.options ?? []
|
||||||
if (options.length > 0) {
|
if (options.length > 0) {
|
||||||
return
|
return
|
||||||
}
|
} else {
|
||||||
else{
|
return window.open('/character/' + (child.value || child.name), '_blank')
|
||||||
return window.open("/character/" + (child.value || child.name),"_blank")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -40,12 +39,14 @@ export default defineComponent(async () => {
|
|||||||
|
|
||||||
// let checkTimer: NodeJS.Timeout
|
// let checkTimer: NodeJS.Timeout
|
||||||
|
|
||||||
|
|
||||||
const adventure = await api.adventures()
|
const adventure = await api.adventures()
|
||||||
|
|
||||||
return () => (
|
return () => (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<div class="bg-no-repeat h-auto min-h-full pt-8 pb-12 pl-4" style={`background-image: url('${getImageURL('home.jpg')}');background-size: 100% 100%;`}>
|
<div
|
||||||
|
class="bg-no-repeat h-auto min-h-full pt-8 pb-12 pl-4"
|
||||||
|
style={`background-image: url('${getImageURL('home.jpg')}');background-size: 100% 100%;`}
|
||||||
|
>
|
||||||
{renderList(adventure, (job) => (
|
{renderList(adventure, (job) => (
|
||||||
<div class="flex flex-row">
|
<div class="flex flex-row">
|
||||||
<div
|
<div
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" name="index" setup>
|
<script lang="ts" name="index" setup>
|
||||||
import { useDialog } from '@/components/hooks/dialog';
|
import { useDialog } from '@/components/hooks/dialog'
|
||||||
|
|
||||||
const { render } = useDialog()
|
const { render } = useDialog()
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ const routes: RouteRecordRaw[] = [
|
|||||||
{
|
{
|
||||||
path: '/',
|
path: '/',
|
||||||
name: 'home',
|
name: 'home',
|
||||||
component: (() => import('@/pages/Home/Index.vue')),
|
component: () => import('@/pages/Home/Index.vue'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/character/:alter',
|
path: '/character/:alter',
|
||||||
@@ -16,13 +16,13 @@ const routes: RouteRecordRaw[] = [
|
|||||||
},
|
},
|
||||||
props: true,
|
props: true,
|
||||||
name: 'character',
|
name: 'character',
|
||||||
component: (() => import('@/pages/Character/Index.vue')),
|
component: () => import('@/pages/Character/Index.vue'),
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: '/character/equipment/:alter',
|
path: '/character/equipment/:alter',
|
||||||
name: 'equipment',
|
name: 'equipment',
|
||||||
props: true,
|
props: true,
|
||||||
component: (() => import('@/pages/Character/EquipmentDictionary/Index.vue')),
|
component: () => import('@/pages/Character/EquipmentDictionary/Index.vue'),
|
||||||
},
|
},
|
||||||
// {
|
// {
|
||||||
// path: '/character/equipment/:alter',
|
// path: '/character/equipment/:alter',
|
||||||
@@ -34,15 +34,16 @@ const routes: RouteRecordRaw[] = [
|
|||||||
path: '/character/skill/:alter',
|
path: '/character/skill/:alter',
|
||||||
name: 'skill',
|
name: 'skill',
|
||||||
props: true,
|
props: true,
|
||||||
component: (() => import('@/pages/Character/Skill/index.vue')),
|
component: () => import('@/pages/Character/Skill/index.vue'),
|
||||||
},{
|
},
|
||||||
|
{
|
||||||
path: '/character/forge/:alter',
|
path: '/character/forge/:alter',
|
||||||
name: 'forge',
|
name: 'forge',
|
||||||
props: true,
|
props: true,
|
||||||
component: (() => import('@/pages/Character/Forge/index.vue')),
|
component: () => import('@/pages/Character/Forge/index.vue'),
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
const router = createRouter({
|
const router = createRouter({
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ export interface IConfig {
|
|||||||
DSB: boolean
|
DSB: boolean
|
||||||
/** 奶 */
|
/** 奶 */
|
||||||
BUFF: boolean
|
BUFF: boolean
|
||||||
|
options: Record<string, number>
|
||||||
}
|
}
|
||||||
|
|
||||||
const defaultEqusConfig = {
|
const defaultEqusConfig = {
|
||||||
@@ -92,6 +93,7 @@ export const useConfigStore = defineStore('configStore', () => {
|
|||||||
bindAwake: 50,
|
bindAwake: 50,
|
||||||
DSB: false,
|
DSB: false,
|
||||||
BUFF: false,
|
BUFF: false,
|
||||||
|
options:{}
|
||||||
})
|
})
|
||||||
|
|
||||||
const skillCountConfig = ref<IResultSkillCount[]>([])
|
const skillCountConfig = ref<IResultSkillCount[]>([])
|
||||||
@@ -120,6 +122,7 @@ export const useConfigStore = defineStore('configStore', () => {
|
|||||||
bindAwake: 50,
|
bindAwake: 50,
|
||||||
DSB: false,
|
DSB: false,
|
||||||
BUFF: false,
|
BUFF: false,
|
||||||
|
options:{}
|
||||||
}
|
}
|
||||||
if (!config.value?.equips) config.value.equips = {}
|
if (!config.value?.equips) config.value.equips = {}
|
||||||
if (!config.value?.skills) config.value.skills = {}
|
if (!config.value?.skills) config.value.skills = {}
|
||||||
@@ -127,6 +130,7 @@ export const useConfigStore = defineStore('configStore', () => {
|
|||||||
if (!config.value?.avatar) config.value.avatar = {}
|
if (!config.value?.avatar) config.value.avatar = {}
|
||||||
if (!config.value?.sundry) config.value.sundry = {}
|
if (!config.value?.sundry) config.value.sundry = {}
|
||||||
if (!config.value?.bindAwake) config.value.bindAwake = 50
|
if (!config.value?.bindAwake) config.value.bindAwake = 50
|
||||||
|
if (!config.value?.options) config.value.options = {}
|
||||||
|
|
||||||
const part = [...infoStore.parts, '宠物', '副武器'].filter(
|
const part = [...infoStore.parts, '宠物', '副武器'].filter(
|
||||||
(a) => !config.value?.equips.hasOwnProperty(a),
|
(a) => !config.value?.equips.hasOwnProperty(a),
|
||||||
@@ -147,6 +151,11 @@ export const useConfigStore = defineStore('configStore', () => {
|
|||||||
config.value && (config.value.avatar[p] = { ...defaultAvatarConfig })
|
config.value && (config.value.avatar[p] = { ...defaultAvatarConfig })
|
||||||
})
|
})
|
||||||
|
|
||||||
|
infoStore.options.forEach((option) => {
|
||||||
|
if(Object.keys(config.value.options).includes(option.id.toString())) return
|
||||||
|
config.value.options[option.id.toString()] = 0
|
||||||
|
})
|
||||||
|
|
||||||
skillIDs.forEach((id) => {
|
skillIDs.forEach((id) => {
|
||||||
config.value &&
|
config.value &&
|
||||||
(config.value.skills[id] = {
|
(config.value.skills[id] = {
|
||||||
@@ -168,7 +177,10 @@ export const useConfigStore = defineStore('configStore', () => {
|
|||||||
const alter = infoStore.infos?.alter
|
const alter = infoStore.infos?.alter
|
||||||
if (alter) {
|
if (alter) {
|
||||||
localStorage.setItem(`dcalc/${alter}/config`, JSON.stringify(config.value))
|
localStorage.setItem(`dcalc/${alter}/config`, JSON.stringify(config.value))
|
||||||
localStorage.setItem(`dcalc/${alter}/config/skillCount`, JSON.stringify(skillCountConfig.value))
|
localStorage.setItem(
|
||||||
|
`dcalc/${alter}/config/skillCount`,
|
||||||
|
JSON.stringify(skillCountConfig.value),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -203,7 +215,7 @@ export const useConfigStore = defineStore('configStore', () => {
|
|||||||
skills: [],
|
skills: [],
|
||||||
info: [],
|
info: [],
|
||||||
suits: [],
|
suits: [],
|
||||||
buffer:false
|
buffer: false,
|
||||||
},
|
},
|
||||||
{ resetOnExecute: false },
|
{ resetOnExecute: false },
|
||||||
)
|
)
|
||||||
@@ -215,6 +227,6 @@ export const useConfigStore = defineStore('configStore', () => {
|
|||||||
calc,
|
calc,
|
||||||
result,
|
result,
|
||||||
chooseEqu,
|
chooseEqu,
|
||||||
skillCountConfig
|
skillCountConfig,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { createPinia } from "pinia"
|
import { createPinia } from 'pinia'
|
||||||
|
|
||||||
export * from "./info"
|
export * from './info'
|
||||||
export * from "./config"
|
export * from './config'
|
||||||
|
|
||||||
export const pinia = createPinia()
|
export const pinia = createPinia()
|
||||||
|
|||||||
@@ -26,13 +26,18 @@ export const useInfoStore = defineStore('infoStore', () => {
|
|||||||
|
|
||||||
const sundries = computed(() => infos.value?.sundry ?? {})
|
const sundries = computed(() => infos.value?.sundry ?? {})
|
||||||
|
|
||||||
|
const options = computed(() => infos.value?.options ?? [])
|
||||||
|
|
||||||
const standardUUID = ref<string>()
|
const standardUUID = ref<string>()
|
||||||
|
|
||||||
const setStandard = (result?: IResult,skillCount?:{
|
const setStandard = (
|
||||||
count: number;
|
result?: IResult,
|
||||||
mode: string;
|
skillCount?: {
|
||||||
name: string;
|
count: number
|
||||||
}[]) => {
|
mode: string
|
||||||
|
name: string
|
||||||
|
}[],
|
||||||
|
) => {
|
||||||
if (!result) {
|
if (!result) {
|
||||||
!!standardUUID.value && sessionStorage.removeItem(standardUUID.value)
|
!!standardUUID.value && sessionStorage.removeItem(standardUUID.value)
|
||||||
standardUUID.value = undefined
|
standardUUID.value = undefined
|
||||||
@@ -45,7 +50,7 @@ export const useInfoStore = defineStore('infoStore', () => {
|
|||||||
const standard = computed(() => {
|
const standard = computed(() => {
|
||||||
const value = sessionStorage.getItem(standardUUID.value ?? '')
|
const value = sessionStorage.getItem(standardUUID.value ?? '')
|
||||||
if (!value) return undefined
|
if (!value) return undefined
|
||||||
else return JSON.parse(value) as {skills:IResultSkill[],skillCount:IResultSkillCount[]}
|
else return JSON.parse(value) as { skills: IResultSkill[]; skillCount: IResultSkillCount[] }
|
||||||
})
|
})
|
||||||
|
|
||||||
const parts = [
|
const parts = [
|
||||||
@@ -107,6 +112,7 @@ export const useInfoStore = defineStore('infoStore', () => {
|
|||||||
jades,
|
jades,
|
||||||
setStandard,
|
setStandard,
|
||||||
standard,
|
standard,
|
||||||
sundries
|
sundries,
|
||||||
|
options
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
+91
-36
@@ -1,26 +1,54 @@
|
|||||||
@use "./animation.scss";
|
@use './animation.scss';
|
||||||
|
|
||||||
.text-shadow {
|
.text-shadow {
|
||||||
text-shadow: 0 0 1px #000, 0 0 1px #000, 0 0 1px #000, 0 0 1px #000,
|
text-shadow:
|
||||||
0 0 1px #000, 0 0 1px #000, 0 0 1px #000, 0 0 1px #000, 0 0 1px #000,
|
0 0 1px #000,
|
||||||
0 0 1px #000, 0 0 1px #000, 0 0 1px #000, 0 0 1px #000, 0 0 1px #000,
|
0 0 1px #000,
|
||||||
0 0 1px #000, 0 0 1px #000, 0 0 1px #000, 0 0 1px #000, 0 0 1px #000,
|
0 0 1px #000,
|
||||||
0 0 1px #000, 0 0 1px #000, 0 0 1px #000, 0 0 1px #000, 0 0 1px #000,
|
0 0 1px #000,
|
||||||
0 0 1px #000, 0 0 1px #000, 0 0 1px #000, 0 0 1px #000, 0 0 1px #000,
|
0 0 1px #000,
|
||||||
0 0 1px #000, 0 0 1px #000, 0 0 1px #000, 0 0 1px #000, 0 0 1px #000;
|
0 0 1px #000,
|
||||||
|
0 0 1px #000,
|
||||||
|
0 0 1px #000,
|
||||||
|
0 0 1px #000,
|
||||||
|
0 0 1px #000,
|
||||||
|
0 0 1px #000,
|
||||||
|
0 0 1px #000,
|
||||||
|
0 0 1px #000,
|
||||||
|
0 0 1px #000,
|
||||||
|
0 0 1px #000,
|
||||||
|
0 0 1px #000,
|
||||||
|
0 0 1px #000,
|
||||||
|
0 0 1px #000,
|
||||||
|
0 0 1px #000,
|
||||||
|
0 0 1px #000,
|
||||||
|
0 0 1px #000,
|
||||||
|
0 0 1px #000,
|
||||||
|
0 0 1px #000,
|
||||||
|
0 0 1px #000,
|
||||||
|
0 0 1px #000,
|
||||||
|
0 0 1px #000,
|
||||||
|
0 0 1px #000,
|
||||||
|
0 0 1px #000,
|
||||||
|
0 0 1px #000,
|
||||||
|
0 0 1px #000,
|
||||||
|
0 0 1px #000,
|
||||||
|
0 0 1px #000,
|
||||||
|
0 0 1px #000,
|
||||||
|
0 0 1px #000;
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: "dcalc";
|
font-family: 'dcalc';
|
||||||
src: url("@/assets/fonts/dcalc.ttf");
|
src: url('@/assets/fonts/dcalc.ttf');
|
||||||
}
|
}
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
--cursor-pointer: url("@/assets/cursor/basic.cur"),
|
--cursor-pointer:
|
||||||
url("@/assets/cursor/cursor.png"), pointer !important;
|
url('@/assets/cursor/basic.cur'), url('@/assets/cursor/cursor.png'), pointer !important;
|
||||||
--cursor-active: url("@/assets/cursor/basic_press.cur"),
|
--cursor-active:
|
||||||
url("@/assets/cursor/cursor.png"), pointer !important;
|
url('@/assets/cursor/basic_press.cur'), url('@/assets/cursor/cursor.png'), pointer !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
html,
|
html,
|
||||||
@@ -39,16 +67,44 @@ body,
|
|||||||
|
|
||||||
* {
|
* {
|
||||||
// font-family: "ArkPixel", "Consola", sans-serif;
|
// font-family: "ArkPixel", "Consola", sans-serif;
|
||||||
font-family: "dcalc", "SimSun";
|
font-family: 'dcalc', 'SimSun';
|
||||||
// font-family: "STSong";
|
// font-family: "STSong";
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
text-shadow: 0 0 1px #000, 0 0 1px #000, 0 0 1px #000, 0 0 1px #000,
|
text-shadow:
|
||||||
0 0 1px #000, 0 0 1px #000, 0 0 1px #000, 0 0 1px #000, 0 0 1px #000,
|
0 0 1px #000,
|
||||||
0 0 1px #000, 0 0 1px #000, 0 0 1px #000, 0 0 1px #000, 0 0 1px #000,
|
0 0 1px #000,
|
||||||
0 0 1px #000, 0 0 1px #000, 0 0 1px #000, 0 0 1px #000, 0 0 1px #000,
|
0 0 1px #000,
|
||||||
0 0 1px #000, 0 0 1px #000, 0 0 1px #000, 0 0 1px #000, 0 0 1px #000,
|
0 0 1px #000,
|
||||||
0 0 1px #000, 0 0 1px #000, 0 0 1px #000, 0 0 1px #000, 0 0 1px #000,
|
0 0 1px #000,
|
||||||
0 0 1px #000, 0 0 1px #000, 0 0 1px #000, 0 0 1px #000, 0 0 1px #000;
|
0 0 1px #000,
|
||||||
|
0 0 1px #000,
|
||||||
|
0 0 1px #000,
|
||||||
|
0 0 1px #000,
|
||||||
|
0 0 1px #000,
|
||||||
|
0 0 1px #000,
|
||||||
|
0 0 1px #000,
|
||||||
|
0 0 1px #000,
|
||||||
|
0 0 1px #000,
|
||||||
|
0 0 1px #000,
|
||||||
|
0 0 1px #000,
|
||||||
|
0 0 1px #000,
|
||||||
|
0 0 1px #000,
|
||||||
|
0 0 1px #000,
|
||||||
|
0 0 1px #000,
|
||||||
|
0 0 1px #000,
|
||||||
|
0 0 1px #000,
|
||||||
|
0 0 1px #000,
|
||||||
|
0 0 1px #000,
|
||||||
|
0 0 1px #000,
|
||||||
|
0 0 1px #000,
|
||||||
|
0 0 1px #000,
|
||||||
|
0 0 1px #000,
|
||||||
|
0 0 1px #000,
|
||||||
|
0 0 1px #000,
|
||||||
|
0 0 1px #000,
|
||||||
|
0 0 1px #000,
|
||||||
|
0 0 1px #000,
|
||||||
|
0 0 1px #000;
|
||||||
// image-rendering:pixelated;
|
// image-rendering:pixelated;
|
||||||
// text-rendering: geometricPrecision;
|
// text-rendering: geometricPrecision;
|
||||||
// letter-spacing: -0.5px;
|
// letter-spacing: -0.5px;
|
||||||
@@ -91,12 +147,12 @@ body,
|
|||||||
::-webkit-scrollbar-button:vertical:single-button:start {
|
::-webkit-scrollbar-button:vertical:single-button:start {
|
||||||
width: 11px;
|
width: 11px;
|
||||||
// 添加标题栏后调整相关位置
|
// 添加标题栏后调整相关位置
|
||||||
background: url("@/assets/img/icon/up.png") 0px 1px no-repeat;
|
background: url('@/assets/img/icon/up.png') 0px 1px no-repeat;
|
||||||
}
|
}
|
||||||
|
|
||||||
::-webkit-scrollbar-button:vertical:single-button:end {
|
::-webkit-scrollbar-button:vertical:single-button:end {
|
||||||
width: 11px;
|
width: 11px;
|
||||||
background: url("@/assets/img/icon/down.png") 0px 1px no-repeat;
|
background: url('@/assets/img/icon/down.png') 0px 1px no-repeat;
|
||||||
}
|
}
|
||||||
|
|
||||||
.divider {
|
.divider {
|
||||||
@@ -140,10 +196,10 @@ body,
|
|||||||
.name {
|
.name {
|
||||||
padding: 0px 5px 0px 5px;
|
padding: 0px 5px 0px 5px;
|
||||||
&::after {
|
&::after {
|
||||||
content: "";
|
content: '';
|
||||||
width: 210px;
|
width: 210px;
|
||||||
height: 8px;
|
height: 8px;
|
||||||
background: url("@/assets/img/underline.png");
|
background: url('@/assets/img/underline.png');
|
||||||
display: block;
|
display: block;
|
||||||
background-size: contain;
|
background-size: contain;
|
||||||
left: 5px;
|
left: 5px;
|
||||||
@@ -197,7 +253,7 @@ body,
|
|||||||
|
|
||||||
.app-header {
|
.app-header {
|
||||||
// -webkit-app-region: drag;
|
// -webkit-app-region: drag;
|
||||||
background-image: url("@/assets/img/control/title.png");
|
background-image: url('@/assets/img/control/title.png');
|
||||||
background-size: 100% 100%;
|
background-size: 100% 100%;
|
||||||
color: #9d8c5b;
|
color: #9d8c5b;
|
||||||
border-top: 1px solid #6c81a7;
|
border-top: 1px solid #6c81a7;
|
||||||
@@ -206,7 +262,7 @@ body,
|
|||||||
|
|
||||||
.min-icon {
|
.min-icon {
|
||||||
-webkit-app-region: no-drag;
|
-webkit-app-region: no-drag;
|
||||||
background: url("@/assets/img/icon/min.png") no-repeat;
|
background: url('@/assets/img/icon/min.png') no-repeat;
|
||||||
|
|
||||||
background-size: 10px 10px;
|
background-size: 10px 10px;
|
||||||
background-position: center;
|
background-position: center;
|
||||||
@@ -214,7 +270,7 @@ body,
|
|||||||
|
|
||||||
.close-icon {
|
.close-icon {
|
||||||
-webkit-app-region: no-drag;
|
-webkit-app-region: no-drag;
|
||||||
background: url("@/assets/img/icon/exit.png") no-repeat;
|
background: url('@/assets/img/icon/exit.png') no-repeat;
|
||||||
background-size: 10px 10px;
|
background-size: 10px 10px;
|
||||||
background-position: center;
|
background-position: center;
|
||||||
}
|
}
|
||||||
@@ -372,32 +428,31 @@ body,
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
.lvInfo {
|
.lvInfo {
|
||||||
background-image: url("@/assets/img/specificity/lv.png");
|
background-image: url('@/assets/img/specificity/lv.png');
|
||||||
background-repeat: no-repeat !important;
|
background-repeat: no-repeat !important;
|
||||||
background-size: auto auto !important;
|
background-size: auto auto !important;
|
||||||
width: 30px;
|
width: 30px;
|
||||||
height: 16px;
|
height: 16px;
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
color:#4E3D1B
|
color: #4e3d1b;
|
||||||
}
|
}
|
||||||
|
|
||||||
.lvInfoActive {
|
.lvInfoActive {
|
||||||
background-image: url("@/assets/img/specificity/lv_active.png");
|
background-image: url('@/assets/img/specificity/lv_active.png');
|
||||||
background-repeat: no-repeat !important;
|
background-repeat: no-repeat !important;
|
||||||
background-size: auto auto !important;
|
background-size: auto auto !important;
|
||||||
width: 30px;
|
width: 30px;
|
||||||
height: 16px;
|
height: 16px;
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
color:#FEB300
|
color: #feb300;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.lvInfoMaster {
|
.lvInfoMaster {
|
||||||
background-image: url("@/assets/img/specificity/lv_master.png");
|
background-image: url('@/assets/img/specificity/lv_master.png');
|
||||||
background-repeat: no-repeat !important;
|
background-repeat: no-repeat !important;
|
||||||
background-size: auto auto !important;
|
background-size: auto auto !important;
|
||||||
width: 30px;
|
width: 30px;
|
||||||
height: 16px;
|
height: 16px;
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
color:#FEB300
|
color: #feb300;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,13 +36,11 @@
|
|||||||
// 极诣·契魔者
|
// 极诣·契魔者
|
||||||
.demon_slayer {
|
.demon_slayer {
|
||||||
background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_02_02.png) no-repeat;
|
background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_02_02.png) no-repeat;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 极诣·流浪武士
|
// 极诣·流浪武士
|
||||||
.vegabond {
|
.vegabond {
|
||||||
background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_02_03.png) no-repeat;
|
background: url(https://bbscdn.df.nexon.com/pg/characters/img/main/mc_02_03.png) no-repeat;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 极诣·刃影
|
// 极诣·刃影
|
||||||
|
|||||||
@@ -1,5 +1,11 @@
|
|||||||
@mixin icon-style($icon-name, $width: 20px, $height: 20px, $size: 100% 100%, $position: center center) {
|
@mixin icon-style(
|
||||||
background-image: url("@/assets/img/icon/#{$icon-name}.png") !important;
|
$icon-name,
|
||||||
|
$width: 20px,
|
||||||
|
$height: 20px,
|
||||||
|
$size: 100% 100%,
|
||||||
|
$position: center center
|
||||||
|
) {
|
||||||
|
background-image: url('@/assets/img/icon/#{$icon-name}.png') !important;
|
||||||
background-repeat: no-repeat !important;
|
background-repeat: no-repeat !important;
|
||||||
background-size: $size !important;
|
background-size: $size !important;
|
||||||
background-position: $position !important;
|
background-position: $position !important;
|
||||||
@@ -7,117 +13,116 @@
|
|||||||
height: $height !important;
|
height: $height !important;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background-image: url("@/assets/img/icon/#{$icon-name}_hover.png") !important;
|
background-image: url('@/assets/img/icon/#{$icon-name}_hover.png') !important;
|
||||||
}
|
}
|
||||||
&:active {
|
&:active {
|
||||||
background-image: url("@/assets/img/icon/#{$icon-name}_active.png") !important;
|
background-image: url('@/assets/img/icon/#{$icon-name}_active.png') !important;
|
||||||
}
|
}
|
||||||
&:disabled {
|
&:disabled {
|
||||||
background-image: url("@/assets/img/icon/#{$icon-name}_disabled.png") !important;
|
background-image: url('@/assets/img/icon/#{$icon-name}_disabled.png') !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-reset {
|
.icon-reset {
|
||||||
@include icon-style("reset");
|
@include icon-style('reset');
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-set {
|
.icon-set {
|
||||||
@include icon-style("set");
|
@include icon-style('set');
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-prev {
|
.icon-prev {
|
||||||
@include icon-style("prev", 16px, 16px);
|
@include icon-style('prev', 16px, 16px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-next {
|
.icon-next {
|
||||||
@include icon-style("next", 16px, 16px);
|
@include icon-style('next', 16px, 16px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-dropdown {
|
.icon-dropdown {
|
||||||
@include icon-style("dropdown", 16px, 16px);
|
@include icon-style('dropdown', 16px, 16px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-search {
|
.icon-search {
|
||||||
@include icon-style("search");
|
@include icon-style('search');
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-increase {
|
.icon-increase {
|
||||||
@include icon-style("increase");
|
@include icon-style('increase');
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-reduce {
|
.icon-reduce {
|
||||||
@include icon-style("reduce");
|
@include icon-style('reduce');
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-plus {
|
.icon-plus {
|
||||||
@include icon-style("plus");
|
@include icon-style('plus');
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-detail {
|
.icon-detail {
|
||||||
@include icon-style("detail");
|
@include icon-style('detail');
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-home {
|
.icon-home {
|
||||||
@include icon-style("home");
|
@include icon-style('home');
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-reflesh {
|
.icon-reflesh {
|
||||||
@include icon-style("reflesh");
|
@include icon-style('reflesh');
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-update {
|
.icon-update {
|
||||||
@include icon-style("update");
|
@include icon-style('update');
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-share {
|
.icon-share {
|
||||||
@include icon-style("share");
|
@include icon-style('share');
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-import {
|
.icon-import {
|
||||||
@include icon-style("import");
|
@include icon-style('import');
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-menu-drug {
|
.icon-menu-drug {
|
||||||
@include icon-style("menu/drug", 20px, 20px, auto 100%);
|
@include icon-style('menu/drug', 20px, 20px, auto 100%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-menu-specificity {
|
.icon-menu-specificity {
|
||||||
@include icon-style("menu/specificity", 20px, 20px, auto 100%);
|
@include icon-style('menu/specificity', 20px, 20px, auto 100%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-menu-favourite {
|
.icon-menu-favourite {
|
||||||
@include icon-style("menu/favourite", 20px, 20px, auto 100%);
|
@include icon-style('menu/favourite', 20px, 20px, auto 100%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-menu-recommend {
|
.icon-menu-recommend {
|
||||||
@include icon-style("menu/recommend", 20px, 20px, auto 100%);
|
@include icon-style('menu/recommend', 20px, 20px, auto 100%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-menu-set {
|
.icon-menu-set {
|
||||||
@include icon-style("menu/set", 20px, 20px, auto 100%);
|
@include icon-style('menu/set', 20px, 20px, auto 100%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-max {
|
.icon-max {
|
||||||
@include icon-style("max");
|
@include icon-style('max');
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-min {
|
.icon-min {
|
||||||
@include icon-style("min");
|
@include icon-style('min');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.icon-increase-little {
|
.icon-increase-little {
|
||||||
@include icon-style("increase",16px, 16px);
|
@include icon-style('increase', 16px, 16px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-reduce-little {
|
.icon-reduce-little {
|
||||||
@include icon-style("reduce", 16px, 16px);
|
@include icon-style('reduce', 16px, 16px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-max-little {
|
.icon-max-little {
|
||||||
@include icon-style("max", 16px, 16px);
|
@include icon-style('max', 16px, 16px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-min-little {
|
.icon-min-little {
|
||||||
@include icon-style("min", 16px, 16px);
|
@include icon-style('min', 16px, 16px);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
@use "./app.scss";
|
@use './app.scss';
|
||||||
@use "./icon.scss";
|
@use './icon.scss';
|
||||||
@use "./char-img.scss"
|
@use './char-img.scss';
|
||||||
|
|||||||
+79
-74
@@ -2,9 +2,9 @@ export function in_range(num: number, start: number, end: number) {
|
|||||||
return start <= num && num <= end
|
return start <= num && num <= end
|
||||||
}
|
}
|
||||||
|
|
||||||
export function to_percent(num?: number, defaultValue: number = 0, suffix = "", withPlus = false) {
|
export function to_percent(num?: number, defaultValue: number = 0, suffix = '', withPlus = false) {
|
||||||
num = num ?? defaultValue
|
num = num ?? defaultValue
|
||||||
return (num > 0 && withPlus ? "+" : "") + num?.multiply(100).round(2).toString().concat(suffix)
|
return (num > 0 && withPlus ? '+' : '') + num?.multiply(100).round(2).toString().concat(suffix)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function get_num(num?: number, defaultValue: number = 0) {
|
export function get_num(num?: number, defaultValue: number = 0) {
|
||||||
@@ -13,14 +13,14 @@ export function get_num(num?: number, defaultValue: number = 0) {
|
|||||||
|
|
||||||
export function format_string(str: string, params: any = {}, ...args: any[]) {
|
export function format_string(str: string, params: any = {}, ...args: any[]) {
|
||||||
let num = 0
|
let num = 0
|
||||||
str = str.replace(/{}/g, match => {
|
str = str.replace(/{}/g, (match) => {
|
||||||
return args[num++] ?? match
|
return args[num++] ?? match
|
||||||
})
|
})
|
||||||
str = str.replace(/{\d+}/g, match => {
|
str = str.replace(/{\d+}/g, (match) => {
|
||||||
const i = Number.parseInt(match.slice(1, -1))
|
const i = Number.parseInt(match.slice(1, -1))
|
||||||
return args[i] ?? match
|
return args[i] ?? match
|
||||||
})
|
})
|
||||||
str = str.replace(/{\w+}/g, match => {
|
str = str.replace(/{\w+}/g, (match) => {
|
||||||
const name = match.slice(1, -1)
|
const name = match.slice(1, -1)
|
||||||
return params[name] ?? match
|
return params[name] ?? match
|
||||||
})
|
})
|
||||||
@@ -29,11 +29,11 @@ export function format_string(str: string, params: any = {}, ...args: any[]) {
|
|||||||
|
|
||||||
export function format_bytes(bytes: number, decimals = 2) {
|
export function format_bytes(bytes: number, decimals = 2) {
|
||||||
if (bytes === 0) {
|
if (bytes === 0) {
|
||||||
return "0 Bytes"
|
return '0 Bytes'
|
||||||
}
|
}
|
||||||
const k = 1024
|
const k = 1024
|
||||||
const dm = decimals < 0 ? 0 : decimals
|
const dm = decimals < 0 ? 0 : decimals
|
||||||
const sizes = ["Bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"]
|
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
|
||||||
|
|
||||||
const i = Math.floor(Math.log(bytes) / Math.log(k))
|
const i = Math.floor(Math.log(bytes) / Math.log(k))
|
||||||
|
|
||||||
@@ -58,14 +58,14 @@ export function cartesian<T = any>(...arr: T[][]): T[][] {
|
|||||||
return arr.reduce(
|
return arr.reduce(
|
||||||
(a, b) => {
|
(a, b) => {
|
||||||
const ret: T[][] = []
|
const ret: T[][] = []
|
||||||
a.forEach(a => {
|
a.forEach((a) => {
|
||||||
b.forEach(b => {
|
b.forEach((b) => {
|
||||||
ret.push(a.concat([b]))
|
ret.push(a.concat([b]))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
return ret
|
return ret
|
||||||
},
|
},
|
||||||
[[]] as T[][]
|
[[]] as T[][],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,7 +95,7 @@ export function debounce_last(func: Function, wait: number) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function padding(num: number | string, length: number): string {
|
export function padding(num: number | string, length: number): string {
|
||||||
if ((`${num}`).length >= length) {
|
if (`${num}`.length >= length) {
|
||||||
return `${num}`
|
return `${num}`
|
||||||
}
|
}
|
||||||
return padding(`0${num}`, length)
|
return padding(`0${num}`, length)
|
||||||
@@ -106,7 +106,10 @@ export function format_float(f: number, digit: number = 2) {
|
|||||||
return (f * m).round(10) / m
|
return (f * m).round(10) / m
|
||||||
}
|
}
|
||||||
|
|
||||||
export function mapRecord<T extends keyof any, K>(status: Record<T, K>, callback: (value: K, key: T) => K) {
|
export function mapRecord<T extends keyof any, K>(
|
||||||
|
status: Record<T, K>,
|
||||||
|
callback: (value: K, key: T) => K,
|
||||||
|
) {
|
||||||
const new_status = {} as Record<T, K>
|
const new_status = {} as Record<T, K>
|
||||||
for (const key in status) {
|
for (const key in status) {
|
||||||
const value = callback(status[key], key)
|
const value = callback(status[key], key)
|
||||||
@@ -172,19 +175,19 @@ export function toObj(data: any): any {
|
|||||||
const temp = {}
|
const temp = {}
|
||||||
for (const key in data) {
|
for (const key in data) {
|
||||||
try {
|
try {
|
||||||
if (typeof data[key] === "number" || typeof data[key] === "string") {
|
if (typeof data[key] === 'number' || typeof data[key] === 'string') {
|
||||||
Object.defineProperty(temp, key, {
|
Object.defineProperty(temp, key, {
|
||||||
value: data[key],
|
value: data[key],
|
||||||
writable: true,
|
writable: true,
|
||||||
enumerable: true,
|
enumerable: true,
|
||||||
configurable: true
|
configurable: true,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
Object.defineProperty(temp, key, {
|
Object.defineProperty(temp, key, {
|
||||||
value: RecordToObj(data[key]),
|
value: RecordToObj(data[key]),
|
||||||
writable: true,
|
writable: true,
|
||||||
enumerable: true,
|
enumerable: true,
|
||||||
configurable: true
|
configurable: true,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
@@ -192,7 +195,7 @@ export function toObj(data: any): any {
|
|||||||
value: data[key],
|
value: data[key],
|
||||||
writable: true,
|
writable: true,
|
||||||
enumerable: true,
|
enumerable: true,
|
||||||
configurable: true
|
configurable: true,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -202,7 +205,7 @@ export function toObj(data: any): any {
|
|||||||
export function toMap(data: any, except: string[] = []) {
|
export function toMap(data: any, except: string[] = []) {
|
||||||
const temp = {}
|
const temp = {}
|
||||||
for (const key in data) {
|
for (const key in data) {
|
||||||
if (typeof data[key] === "object" && data[key].constructor != Array && !except.includes(key)) {
|
if (typeof data[key] === 'object' && data[key].constructor != Array && !except.includes(key)) {
|
||||||
// 需要转换部分,不能是Array,也会被转换
|
// 需要转换部分,不能是Array,也会被转换
|
||||||
const sub = {}
|
const sub = {}
|
||||||
for (const subkey in data[key]) {
|
for (const subkey in data[key]) {
|
||||||
@@ -210,21 +213,21 @@ export function toMap(data: any, except: string[] = []) {
|
|||||||
value: new Map(Object.entries(data[key][subkey])),
|
value: new Map(Object.entries(data[key][subkey])),
|
||||||
writable: true,
|
writable: true,
|
||||||
enumerable: true,
|
enumerable: true,
|
||||||
configurable: true
|
configurable: true,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
Object.defineProperty(temp, key, {
|
Object.defineProperty(temp, key, {
|
||||||
value: sub,
|
value: sub,
|
||||||
writable: true,
|
writable: true,
|
||||||
enumerable: true,
|
enumerable: true,
|
||||||
configurable: true
|
configurable: true,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
Object.defineProperty(temp, key, {
|
Object.defineProperty(temp, key, {
|
||||||
value: data[key],
|
value: data[key],
|
||||||
writable: true,
|
writable: true,
|
||||||
enumerable: true,
|
enumerable: true,
|
||||||
configurable: true
|
configurable: true,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -238,28 +241,31 @@ export function RecordToObj(todo: Record<string, Map<any, any>>) {
|
|||||||
value: Object.fromEntries(todo[key]),
|
value: Object.fromEntries(todo[key]),
|
||||||
writable: true,
|
writable: true,
|
||||||
enumerable: true,
|
enumerable: true,
|
||||||
configurable: true
|
configurable: true,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return temp
|
return temp
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getUuid() {
|
export function getUuid() {
|
||||||
if (typeof crypto === "object") {
|
if (typeof crypto === 'object') {
|
||||||
if (typeof crypto.randomUUID === "function") {
|
if (typeof crypto.randomUUID === 'function') {
|
||||||
return crypto.randomUUID()
|
return crypto.randomUUID()
|
||||||
}
|
}
|
||||||
if (typeof crypto.getRandomValues === "function" && typeof Uint8Array === "function") {
|
if (typeof crypto.getRandomValues === 'function' && typeof Uint8Array === 'function') {
|
||||||
const callback = (c: any) => {
|
const callback = (c: any) => {
|
||||||
const num = Number(c)
|
const num = Number(c)
|
||||||
return (num ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (num / 4)))).toString(16)
|
return (num ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (num / 4)))).toString(
|
||||||
|
16,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
return "10000000-1000-4000-8000-100000000000".replace(/[018]/g, callback)
|
return '10000000-1000-4000-8000-100000000000'.replace(/[018]/g, callback)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let timestamp = new Date().getTime()
|
let timestamp = new Date().getTime()
|
||||||
let perforNow = (typeof performance !== "undefined" && performance.now && performance.now() * 1000) || 0
|
let perforNow =
|
||||||
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, c => {
|
(typeof performance !== 'undefined' && performance.now && performance.now() * 1000) || 0
|
||||||
|
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
|
||||||
let random = Math.random() * 16
|
let random = Math.random() * 16
|
||||||
if (timestamp > 0) {
|
if (timestamp > 0) {
|
||||||
random = Math.trunc((timestamp + random) % 16)
|
random = Math.trunc((timestamp + random) % 16)
|
||||||
@@ -268,90 +274,89 @@ export function getUuid() {
|
|||||||
random = Math.trunc((perforNow + random) % 16)
|
random = Math.trunc((perforNow + random) % 16)
|
||||||
perforNow = Math.floor(perforNow / 16)
|
perforNow = Math.floor(perforNow / 16)
|
||||||
}
|
}
|
||||||
return (c === "x" ? random : (random & 0x3) | 0x8).toString(16)
|
return (c === 'x' ? random : (random & 0x3) | 0x8).toString(16)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export function rarityClass(type: string) {
|
export function rarityClass(type: string) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case "太初":
|
case '太初':
|
||||||
return "primeval"
|
return 'primeval'
|
||||||
case "史诗":
|
case '史诗':
|
||||||
return "epic"
|
return 'epic'
|
||||||
case "神话":
|
case '神话':
|
||||||
return "myth"
|
return 'myth'
|
||||||
case "智慧产物":
|
case '智慧产物':
|
||||||
return "epic"
|
return 'epic'
|
||||||
case "神器":
|
case '神器':
|
||||||
return "artifact"
|
return 'artifact'
|
||||||
case "稀有":
|
case '稀有':
|
||||||
return "rare"
|
return 'rare'
|
||||||
case "传说":
|
case '传说':
|
||||||
return "legend"
|
return 'legend'
|
||||||
case "勇者":
|
case '勇者':
|
||||||
return "chronicle"
|
return 'chronicle'
|
||||||
case "高级":
|
case '高级':
|
||||||
return "advanced"
|
return 'advanced'
|
||||||
default:
|
default:
|
||||||
return "epic"
|
return 'epic'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function formatAttr(type: string, value: number) {
|
export function formatAttr(type: string, value: number) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case "STR":
|
case 'STR':
|
||||||
return `力量 ${value}`
|
return `力量 ${value}`
|
||||||
case "INT":
|
case 'INT':
|
||||||
return `智力 ${value}`
|
return `智力 ${value}`
|
||||||
case "Vitality":
|
case 'Vitality':
|
||||||
return `体力 ${value}`
|
return `体力 ${value}`
|
||||||
case "Spirit":
|
case 'Spirit':
|
||||||
return `精神 ${value}`
|
return `精神 ${value}`
|
||||||
case "AtkP":
|
case 'AtkP':
|
||||||
return `物理攻击力 ${value}`
|
return `物理攻击力 ${value}`
|
||||||
case "AtkM":
|
case 'AtkM':
|
||||||
return `魔法攻击力 ${value}`
|
return `魔法攻击力 ${value}`
|
||||||
case "AtkI":
|
case 'AtkI':
|
||||||
return `独立攻击力 ${value}`
|
return `独立攻击力 ${value}`
|
||||||
case "SkillAttack":
|
case 'SkillAttack':
|
||||||
return `技能伤害 +${(value * 100).toFixed(2)}%`
|
return `技能伤害 +${(value * 100).toFixed(2)}%`
|
||||||
case "Attack":
|
case 'Attack':
|
||||||
return `攻击强化 +${(value).toFixed(1)}%`
|
return `攻击强化 +${value.toFixed(1)}%`
|
||||||
case "Buffer":
|
case 'Buffer':
|
||||||
return `增益量 ${(value)}`
|
return `增益量 ${value}`
|
||||||
default:
|
default:
|
||||||
return `${type} ${value}`
|
return `${type} ${value}`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export const decrypt = (encryptedData: string) => {
|
export const decrypt = (encryptedData: string) => {
|
||||||
try {
|
try {
|
||||||
encryptedData = decodeURIComponent(encryptedData).split("").map(a=>{
|
encryptedData = decodeURIComponent(encryptedData)
|
||||||
|
.split('')
|
||||||
|
.map((a) => {
|
||||||
if (a == '=') {
|
if (a == '=') {
|
||||||
return a
|
return a
|
||||||
}
|
} else {
|
||||||
else{
|
|
||||||
return String.fromCharCode(a.charCodeAt(0) - 1)
|
return String.fromCharCode(a.charCodeAt(0) - 1)
|
||||||
}
|
}
|
||||||
}).join("")
|
})
|
||||||
const decryptedData = atob(encryptedData);
|
.join('')
|
||||||
|
const decryptedData = atob(encryptedData)
|
||||||
|
|
||||||
const len = decryptedData.length;
|
const len = decryptedData.length
|
||||||
const decryptedBinaryOffset = decryptedData.slice(0, len-13);
|
const decryptedBinaryOffset = decryptedData.slice(0, len - 13)
|
||||||
const decryptedTimestamp = decryptedData.slice(len-13, len);
|
const decryptedTimestamp = decryptedData.slice(len - 13, len)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
uid: parseInt(decryptedBinaryOffset, 2),
|
uid: parseInt(decryptedBinaryOffset, 2),
|
||||||
time:parseInt(decryptedTimestamp)
|
time: parseInt(decryptedTimestamp),
|
||||||
}
|
}
|
||||||
}
|
} catch (e) {
|
||||||
catch(e){
|
|
||||||
console.log(e)
|
console.log(e)
|
||||||
return {
|
return {
|
||||||
uid: -1,
|
uid: -1,
|
||||||
time:0
|
time: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+39
-27
@@ -1,8 +1,8 @@
|
|||||||
import type { MaybeRef } from "@vueuse/core"
|
import type { MaybeRef } from '@vueuse/core'
|
||||||
import querystring from "query-string"
|
import querystring from 'query-string'
|
||||||
import { h, isRef } from "vue"
|
import { h, isRef } from 'vue'
|
||||||
import { useRouter } from "vue-router"
|
import { useRouter } from 'vue-router'
|
||||||
import { useDialog } from "@/components/hooks/dialog"
|
import { useDialog } from '@/components/hooks/dialog'
|
||||||
|
|
||||||
interface UseOpenOption {
|
interface UseOpenOption {
|
||||||
/*
|
/*
|
||||||
@@ -16,7 +16,7 @@ interface UseOpenOption {
|
|||||||
/**
|
/**
|
||||||
* 是否打开新页面
|
* 是否打开新页面
|
||||||
*/
|
*/
|
||||||
target?: "_blank" | "_self" | false
|
target?: '_blank' | '_self' | false
|
||||||
|
|
||||||
title?: string
|
title?: string
|
||||||
}
|
}
|
||||||
@@ -25,13 +25,27 @@ export function useOpenWindow(opt?: UseOpenOption & { immediate?: boolean }) {
|
|||||||
const { show, close, randomId } = useDialog()
|
const { show, close, randomId } = useDialog()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
return async (maybeUrl: MaybeRef<string> | (() => string), { width = 0, height = 0, target = "_self", query = {}, title = "DNF计算器 & Colg", scale = 1.0 }: UseOpenOption = {}) => {
|
return async (
|
||||||
let url = isRef(maybeUrl) ? maybeUrl.value : typeof maybeUrl === "function" ? maybeUrl() : maybeUrl
|
maybeUrl: MaybeRef<string> | (() => string),
|
||||||
|
{
|
||||||
|
width = 0,
|
||||||
|
height = 0,
|
||||||
|
target = '_self',
|
||||||
|
query = {},
|
||||||
|
title = 'DNF计算器 & Colg',
|
||||||
|
scale = 1.0,
|
||||||
|
}: UseOpenOption = {},
|
||||||
|
) => {
|
||||||
|
let url = isRef(maybeUrl)
|
||||||
|
? maybeUrl.value
|
||||||
|
: typeof maybeUrl === 'function'
|
||||||
|
? maybeUrl()
|
||||||
|
: maybeUrl
|
||||||
if (!url) {
|
if (!url) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (url.startsWith("/")) {
|
if (url.startsWith('/')) {
|
||||||
url = router.resolve(url).href
|
url = router.resolve(url).href
|
||||||
}
|
}
|
||||||
query.r = `${Math.random()}`
|
query.r = `${Math.random()}`
|
||||||
@@ -40,50 +54,48 @@ export function useOpenWindow(opt?: UseOpenOption & { immediate?: boolean }) {
|
|||||||
let _target = target
|
let _target = target
|
||||||
if (!_target) {
|
if (!_target) {
|
||||||
const rs = await show({
|
const rs = await show({
|
||||||
content: "请确认打开新页面的方式",
|
content: '请确认打开新页面的方式',
|
||||||
okButton: "当前窗口",
|
okButton: '当前窗口',
|
||||||
rejectButton: "新窗口",
|
rejectButton: '新窗口',
|
||||||
cancelButton: true,
|
cancelButton: true,
|
||||||
defaultStatus: "cancel"
|
defaultStatus: 'cancel',
|
||||||
})
|
})
|
||||||
if (rs.isOk) {
|
if (rs.isOk) {
|
||||||
_target = "_self"
|
_target = '_self'
|
||||||
} else if (rs.isReject) {
|
} else if (rs.isReject) {
|
||||||
_target = "_blank"
|
_target = '_blank'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_target == "_blank" || width * height < 1) {
|
if (_target == '_blank' || width * height < 1) {
|
||||||
window.open(url, _target as string)
|
window.open(url, _target as string)
|
||||||
|
} else if (_target == '_self') {
|
||||||
} else if (_target == "_self") {
|
|
||||||
|
|
||||||
const id = randomId()
|
const id = randomId()
|
||||||
const onClose = (e: MessageEvent) => {
|
const onClose = (e: MessageEvent) => {
|
||||||
if (e.data == "close") {
|
if (e.data == 'close') {
|
||||||
close(id)
|
close(id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
window.addEventListener("message", onClose)
|
window.addEventListener('message', onClose)
|
||||||
const temp = await show({
|
const temp = await show({
|
||||||
id,
|
id,
|
||||||
header: title,
|
header: title,
|
||||||
mask: true,
|
mask: true,
|
||||||
scale,
|
scale,
|
||||||
content() {
|
content() {
|
||||||
return h("iframe", {
|
return h('iframe', {
|
||||||
name: Math.random().toString(36).slice(2),
|
name: Math.random().toString(36).slice(2),
|
||||||
referrerpolicy: "no-referrer",
|
referrerpolicy: 'no-referrer',
|
||||||
frameborder: 0,
|
frameborder: 0,
|
||||||
src: url,
|
src: url,
|
||||||
style: {
|
style: {
|
||||||
width: `${width}px`,
|
width: `${width}px`,
|
||||||
height: `${height}px`
|
height: `${height}px`,
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
window.removeEventListener("message", onClose)
|
window.removeEventListener('message', onClose)
|
||||||
return temp
|
return temp
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { defineConfig } from 'unocss'
|
import { defineConfig } from 'unocss'
|
||||||
// import { presetAttributify } from 'unocss'
|
// import { presetAttributify } from 'unocss'
|
||||||
import { blackA, green } from '@radix-ui/colors'
|
// import { blackA, green } from '@radix-ui/colors'
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
// presets: [presetAttributify()],
|
// presets: [presetAttributify()],
|
||||||
|
|||||||
Reference in New Issue
Block a user