Merge pull request #223 from DevDengChao/codex/lint-iot-ai

chore: fix ai and iot lint
master
芋道源码 2026-05-23 22:06:03 +08:00 committed by GitHub
commit 31a7f6248a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
24 changed files with 152 additions and 131 deletions

View File

@ -60,12 +60,12 @@
class="py-0.5 px-2.5"
style="
max-width: 220px;
overflow: hidden;
font-size: 14px;
font-weight: 400;
color: var(--el-text-color-regular);
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
white-space: nowrap;
"
>
{{ conversation.title }}
@ -103,9 +103,9 @@
<div
class="absolute bottom-0 left-0 right-0 px-5 leading-8.75 flex justify-between items-center"
style="
color: var(--el-text-color);
background-color: var(--el-fill-color-extra-light);
box-shadow: 0 0 1px 1px var(--el-border-color-lighter);
color: var(--el-text-color);
"
>
<div

View File

@ -53,10 +53,10 @@
<Icon :icon="getFileIcon(file.name)" class="text-blue-500 mr-2 flex-shrink-0" />
<span
class="font-medium text-gray-900 mr-1 overflow-hidden text-ellipsis whitespace-nowrap flex-1"
>{{ file.name }}</span
>{{ file.name }}</span
>
<span class="text-gray-500 flex-shrink-0 text-11px"
>({{ formatFileSize(file.size) }})</span
>({{ formatFileSize(file.size) }})</span
>
</div>
<div class="flex items-center gap-1 flex-shrink-0 ml-2">
@ -286,27 +286,29 @@ onUnmounted(() => {
--el-button-border-color: transparent;
--el-button-hover-bg-color: var(--el-fill-color-light);
--el-button-hover-border-color: transparent;
color: var(--el-text-color-regular);
}
.upload-btn.has-files {
color: var(--el-color-primary);
--el-button-hover-bg-color: var(--el-color-primary-light-9);
color: var(--el-color-primary);
}
.file-tooltip {
position: absolute;
bottom: calc(100% + 8px);
left: 50%;
transform: translateX(-50%);
z-index: 1000;
max-width: 320px;
min-width: 240px;
padding: 8px;
background: white;
border: 1px solid var(--el-border-color-light);
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
z-index: 1000;
min-width: 240px;
max-width: 320px;
padding: 8px;
transform: translateX(-50%);
box-shadow: 0 4px 12px rgb(0 0 0 / 15%);
animation: fadeInDown 0.2s ease;
}
@ -314,25 +316,25 @@ onUnmounted(() => {
position: absolute;
bottom: -5px;
left: 50%;
transform: translateX(-50%);
width: 0;
height: 0;
border-left: 5px solid transparent;
border-right: 5px solid transparent;
border-top: 5px solid var(--el-border-color-light);
border-right: 5px solid transparent;
border-left: 5px solid transparent;
transform: translateX(-50%);
}
/* Tooltip 箭头伪元素 */
.tooltip-arrow::after {
content: '';
position: absolute;
bottom: 1px;
left: -4px;
width: 0;
height: 0;
border-left: 4px solid transparent;
border-right: 4px solid transparent;
border-top: 4px solid white;
border-right: 4px solid transparent;
border-left: 4px solid transparent;
content: '';
}
@keyframes fadeInDown {
@ -340,6 +342,7 @@ onUnmounted(() => {
opacity: 0;
transform: translateX(-50%) translateY(4px);
}
to {
opacity: 1;
transform: translateX(-50%) translateY(0);
@ -351,6 +354,7 @@ onUnmounted(() => {
opacity: 0;
transform: translateX(-50%) translateY(4px);
}
to {
opacity: 1;
transform: translateX(-50%) translateY(0);
@ -374,6 +378,7 @@ onUnmounted(() => {
.file-list::-webkit-scrollbar-thumb:hover {
background: var(--el-border-color);
}
/* 滚动条样式 */
.file-list::-webkit-scrollbar {
width: 4px;

View File

@ -79,11 +79,11 @@ const toggleExpanded = () => {
}
.max-h-300px::-webkit-scrollbar-thumb {
background: rgba(156, 163, 175, 0.4);
background: rgb(156 163 175 / 40%);
border-radius: 2px;
}
.max-h-300px::-webkit-scrollbar-thumb:hover {
background: rgba(156, 163, 175, 0.6);
background: rgb(156 163 175 / 60%);
}
</style>

View File

@ -228,8 +228,8 @@ onMounted(async () => {
}
.el-tabs__header {
margin: 0 !important;
padding: 0 !important;
margin: 0 !important;
}
.el-tabs__nav-wrap {
@ -241,6 +241,6 @@ onMounted(async () => {
}
.el-tab-pane {
padding: 8px 0 0 0 !important;
padding: 8px 0 0 !important;
}
</style>

View File

@ -57,16 +57,16 @@
class="content-expand"
style="
padding: 10px 20px;
white-space: pre-wrap;
line-height: 1.5;
white-space: pre-wrap;
background-color: #f9f9f9;
border-radius: 4px;
border-left: 3px solid #409eff;
border-radius: 4px;
"
>
<div
class="content-title"
style="margin-bottom: 8px; color: #606266; font-size: 14px; font-weight: bold"
style="margin-bottom: 8px; font-size: 14px; font-weight: bold; color: #606266"
>
完整内容
</div>

View File

@ -143,11 +143,12 @@ defineExpose({
flex-direction: column;
:deep(.el-card__body) {
@extend .hide-scroll-bar;
padding: 0;
overflow-y: auto;
box-sizing: border-box;
flex-grow: 1;
overflow-y: auto;
padding: 0;
@extend .hide-scroll-bar;
}
}

View File

@ -1,9 +1,9 @@
<template>
<div class="flex h-full items-stretch">
<div class="flex h-full items-stretch">
<!-- 模式 -->
<Mode class="flex-none" @generate-music="generateMusic"/>
<Mode class="flex-none" @generate-music="generateMusic" />
<!-- 音频列表 -->
<List ref="listRef" class="flex-auto"/>
<List ref="listRef" class="flex-auto" />
</div>
</template>

View File

@ -2,33 +2,33 @@
<div class="flex items-center justify-between px-2 h-72px bg-[var(--el-bg-color-overlay)] b-solid b-1 b-[var(--el-border-color)] b-l-none">
<!-- 歌曲信息 -->
<div class="flex gap-[10px]">
<el-image src="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png" class="w-[45px]"/>
<el-image src="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png" class="w-[45px]" />
<div>
<div>{{currentSong.name}}</div>
<div class="text-[12px] text-gray-400">{{currentSong.singer}}</div>
<div>{{ currentSong.name }}</div>
<div class="text-[12px] text-gray-400">{{ currentSong.singer }}</div>
</div>
</div>
<!-- 音频controls -->
<div class="flex gap-[12px] items-center">
<Icon icon="majesticons:back-circle" :size="20" class="text-gray-300 cursor-pointer"/>
<Icon :icon="audioProps.paused ? 'mdi:arrow-right-drop-circle' : 'solar:pause-circle-bold'" :size="30" class=" cursor-pointer" @click="toggleStatus('paused')"/>
<Icon icon="majesticons:next-circle" :size="20" class="text-gray-300 cursor-pointer"/>
<Icon icon="majesticons:back-circle" :size="20" class="text-gray-300 cursor-pointer" />
<Icon :icon="audioProps.paused ? 'mdi:arrow-right-drop-circle' : 'solar:pause-circle-bold'" :size="30" class=" cursor-pointer" @click="toggleStatus('paused')" />
<Icon icon="majesticons:next-circle" :size="20" class="text-gray-300 cursor-pointer" />
<div class="flex gap-[16px] items-center">
<span>{{audioProps.currentTime}}</span>
<el-slider v-model="audioProps.duration" color="#409eff" class="w-[160px!important] "/>
<span>{{ audioProps.currentTime }}</span>
<el-slider v-model="audioProps.duration" color="#409eff" class="w-[160px!important] " />
<span>{{ audioProps.duration }}</span>
</div>
<!-- 音频 -->
<audio v-bind="audioProps" ref="audioRef" controls v-show="!audioProps" @timeupdate="audioTimeUpdate">
<source :src="audioUrl"/>
<source :src="audioUrl" />
</audio>
</div>
<!-- 音量控制器 -->
<div class="flex gap-[16px] items-center">
<Icon :icon="audioProps.muted ? 'tabler:volume-off' : 'tabler:volume'" :size="20" class="cursor-pointer" @click="toggleStatus('muted')"/>
<el-slider v-model="audioProps.volume" color="#409eff" class="w-[160px!important] "/>
<Icon :icon="audioProps.muted ? 'tabler:volume-off' : 'tabler:volume'" :size="20" class="cursor-pointer" @click="toggleStatus('muted')" />
<el-slider v-model="audioProps.volume" color="#409eff" class="w-[160px!important] " />
</div>
</div>
</template>

View File

@ -6,26 +6,26 @@
<el-tab-pane v-loading="loading" label="我的创作" name="mine">
<el-row v-if="mySongList.length" :gutter="12">
<el-col v-for="song in mySongList" :key="song.id" :span="24">
<songCard :songInfo="song" @play="setCurrentSong(song)"/>
<songCard :songInfo="song" @play="setCurrentSong(song)" />
</el-col>
</el-row>
<el-empty v-else description="暂无音乐"/>
<el-empty v-else description="暂无音乐" />
</el-tab-pane>
<!-- 试听广场 -->
<el-tab-pane v-loading="loading" label="试听广场" name="square">
<el-row v-if="squareSongList.length" v-loading="loading" :gutter="12">
<el-col v-for="song in squareSongList" :key="song.id" :span="24">
<songCard :songInfo="song" @play="setCurrentSong(song)"/>
<songCard :songInfo="song" @play="setCurrentSong(song)" />
</el-col>
</el-row>
<el-empty v-else description="暂无音乐"/>
<el-empty v-else description="暂无音乐" />
</el-tab-pane>
</el-tabs>
<!-- songInfo -->
<songInfo class="flex-none"/>
<songInfo class="flex-none" />
</div>
<audioBar class="flex-none"/>
<audioBar class="flex-none" />
</div>
</template>
@ -100,6 +100,7 @@ defineExpose({
:deep(.el-tabs) {
display: flex;
flex-direction: column;
.el-tabs__content {
padding: 0 7px;
overflow: auto;

View File

@ -1,9 +1,9 @@
<template>
<div class="flex bg-[var(--el-bg-color-overlay)] p-12px mb-12px rounded-1">
<div class="relative" @click="playSong">
<el-image :src="songInfo.imageUrl" class="flex-none w-80px"/>
<el-image :src="songInfo.imageUrl" class="flex-none w-80px" />
<div class="bg-black bg-op-40 absolute top-0 left-0 w-full h-full flex items-center justify-center cursor-pointer">
<Icon :icon="currentSong.id === songInfo.id ? 'solar:pause-circle-bold':'mdi:arrow-right-drop-circle'" :size="30" />
<Icon :icon="currentSong.id === songInfo.id ? 'solar:pause-circle-bold':'mdi:arrow-right-drop-circle'" :size="30" />
</div>
</div>
<div class="ml-8px">

View File

@ -1,6 +1,6 @@
<template>
<ContentWrap class="w-300px mb-[0!important] line-height-24px">
<el-image :src="currentSong.imageUrl"/>
<el-image :src="currentSong.imageUrl" />
<div class="">{{ currentSong.title }}</div>
<div class="text-[var(--el-text-color-secondary)] text-12px line-clamp-1">
{{ currentSong.desc }}

View File

@ -14,7 +14,7 @@
<Title title="纯音乐" desc="创建一首没有歌词的歌曲">
<template #extra>
<el-switch v-model="formData.pure" size="small"/>
<el-switch v-model="formData.pure" size="small" />
</template>
</Title>

View File

@ -14,7 +14,7 @@
<Title title="音乐风格">
<el-space class="flex-wrap">
<el-tag v-for="tag in tags" :key="tag" round class="mb-8px">{{tag}}</el-tag>
<el-tag v-for="tag in tags" :key="tag" round class="mb-8px">{{ tag }}</el-tag>
</el-space>
<el-button
@ -40,7 +40,7 @@
</Title>
<Title title="音乐/歌曲名称">
<el-input v-model="formData.name" placeholder="请输入音乐/歌曲名称"/>
<el-input v-model="formData.name" placeholder="请输入音乐/歌曲名称" />
</Title>
<Title title="版本">

View File

@ -1,11 +1,11 @@
<template>
<div class="mb-12px">
<div class="flex text-[var(--el-text-color-primary)] justify-between items-center">
<span>{{title}}</span>
<span>{{ title }}</span>
<slot name="extra"></slot>
</div>
<div class="text-[var(--el-text-color-secondary)] text-12px my-8px">
{{desc}}
{{ desc }}
</div>
<slot></slot>
</div>

View File

@ -48,7 +48,7 @@
<el-text type="danger">{{ error }}</el-text>
</div>
<pre v-else-if="testResult" class="result-content"
>{{ JSON.stringify(testResult, null, 2) }}
>{{ JSON.stringify(testResult, null, 2) }}
</pre>
<div v-else> <el-text type="info">点击运行查看结果</el-text> </div>
</div>
@ -237,14 +237,14 @@ defineExpose({
<style lang="css" scoped>
.result-content {
background: white;
padding: 12px;
border-radius: 4px;
max-height: 300px;
padding: 12px;
overflow: auto;
font-family: Monaco, Consolas, monospace;
font-size: 14px;
line-height: 1.5;
white-space: pre-wrap;
background: white;
border-radius: 4px;
}
</style>

View File

@ -110,11 +110,12 @@ watch(copied, (val) => {
flex-direction: column;
:deep(.el-card__body) {
@extend .hide-scroll-bar;
padding: 0;
overflow-y: auto;
box-sizing: border-box;
flex-grow: 1;
overflow-y: auto;
padding: 0;
@extend .hide-scroll-bar;
}
}
</style>

View File

@ -16,7 +16,7 @@
<script setup lang="ts">
const props = withDefaults(
defineProps<{
tags: { label: string; value: string }[]
tags?: { label: string; value: string }[]
modelValue: string
[k: string]: any
}>(),

View File

@ -3,44 +3,44 @@
<div>
<ContentWrap>
<el-descriptions :column="3" border>
<el-descriptions-item label="产品名称">{{ product.name }}</el-descriptions-item>
<el-descriptions-item label="ProductKey">{{ product.productKey }}</el-descriptions-item>
<el-descriptions-item label="设备类型">
<dict-tag :type="DICT_TYPE.IOT_PRODUCT_DEVICE_TYPE" :value="product.deviceType" />
</el-descriptions-item>
<el-descriptions-item label="DeviceName">{{ device.deviceName }}</el-descriptions-item>
<el-descriptions-item label="备注名称">{{ device.nickname }}</el-descriptions-item>
<el-descriptions-item label="当前状态">
<dict-tag :type="DICT_TYPE.IOT_DEVICE_STATE" :value="device.state" />
</el-descriptions-item>
<el-descriptions-item label="创建时间">
{{ formatDate(device.createTime) }}
</el-descriptions-item>
<el-descriptions-item label="激活时间">
{{ formatDate(device.activeTime) }}
</el-descriptions-item>
<el-descriptions-item label="最后上线时间">
{{ formatDate(device.onlineTime) }}
</el-descriptions-item>
<el-descriptions-item label="最后离线时间">
{{ formatDate(device.offlineTime) }}
</el-descriptions-item>
<el-descriptions-item label="设备位置">
<template v-if="hasLocation">
<span class="mr-2">{{ device.longitude }}, {{ device.latitude }}</span>
<el-button type="primary" link @click="openMapDialog">
<Icon icon="ep:location" class="mr-1" />
查看地图
</el-button>
</template>
<span v-else class="text-[var(--el-text-color-secondary)]">暂无位置信息</span>
</el-descriptions-item>
<el-descriptions-item label="认证信息">
<el-button type="primary" @click="handleAuthInfoDialogOpen" plain size="small">
查看
<el-descriptions-item label="产品名称">{{ product.name }}</el-descriptions-item>
<el-descriptions-item label="ProductKey">{{ product.productKey }}</el-descriptions-item>
<el-descriptions-item label="设备类型">
<dict-tag :type="DICT_TYPE.IOT_PRODUCT_DEVICE_TYPE" :value="product.deviceType" />
</el-descriptions-item>
<el-descriptions-item label="DeviceName">{{ device.deviceName }}</el-descriptions-item>
<el-descriptions-item label="备注名称">{{ device.nickname }}</el-descriptions-item>
<el-descriptions-item label="当前状态">
<dict-tag :type="DICT_TYPE.IOT_DEVICE_STATE" :value="device.state" />
</el-descriptions-item>
<el-descriptions-item label="创建时间">
{{ formatDate(device.createTime) }}
</el-descriptions-item>
<el-descriptions-item label="激活时间">
{{ formatDate(device.activeTime) }}
</el-descriptions-item>
<el-descriptions-item label="最后上线时间">
{{ formatDate(device.onlineTime) }}
</el-descriptions-item>
<el-descriptions-item label="最后离线时间">
{{ formatDate(device.offlineTime) }}
</el-descriptions-item>
<el-descriptions-item label="设备位置">
<template v-if="hasLocation">
<span class="mr-2">{{ device.longitude }}, {{ device.latitude }}</span>
<el-button type="primary" link @click="openMapDialog">
<Icon icon="ep:location" class="mr-1" />
查看地图
</el-button>
</el-descriptions-item>
</el-descriptions>
</template>
<span v-else class="text-[var(--el-text-color-secondary)]">暂无位置信息</span>
</el-descriptions-item>
<el-descriptions-item label="认证信息">
<el-button type="primary" @click="handleAuthInfoDialogOpen" plain size="small">
查看
</el-button>
</el-descriptions-item>
</el-descriptions>
</ContentWrap>
<!-- 认证信息弹框 -->

View File

@ -36,7 +36,9 @@
inline-prompt
active-text="定时刷新"
inactive-text="定时刷新"
style="--el-switch-on-color: #13ce66"
style="
--el-switch-on-color: #13ce66"
/>
</el-form-item>
</el-form>

View File

@ -40,7 +40,9 @@
inline-prompt
active-text="定时刷新"
inactive-text="定时刷新"
style="--el-switch-on-color: #13ce66"
style="
--el-switch-on-color: #13ce66"
/>
</el-form-item>
</el-form>

View File

@ -131,22 +131,22 @@ onMounted(() => {
.terminal-card {
margin-top: 32px;
margin-bottom: 8px;
border-radius: 12px;
background-color: #1a1b26;
box-shadow: 0 10px 30px -10px rgba(0, 0, 0, 0.4);
border: 1px solid #24283b;
overflow: hidden;
font-family: 'Fira Code', 'JetBrains Mono', Consolas, Monaco, monospace;
background-color: #1a1b26;
border: 1px solid #24283b;
border-radius: 12px;
box-shadow: 0 10px 30px -10px rgb(0 0 0 / 40%);
}
.terminal-header {
position: relative;
display: flex;
align-items: center;
justify-content: space-between;
padding: 12px 16px;
background-color: #24283b;
border-bottom: 1px solid #16161e;
position: relative;
align-items: center;
justify-content: space-between;
}
.terminal-dots {
@ -160,53 +160,59 @@ onMounted(() => {
border-radius: 50%;
transition: transform 0.2s ease;
}
.dot:hover {
transform: scale(1.2);
}
.dot.red {
background-color: #f7768e;
box-shadow: 0 0 5px rgba(247, 118, 142, 0.4);
box-shadow: 0 0 5px rgb(247 118 142 / 40%);
}
.dot.yellow {
background-color: #e0af68;
box-shadow: 0 0 5px rgba(224, 175, 104, 0.4);
box-shadow: 0 0 5px rgb(224 175 104 / 40%);
}
.dot.green {
background-color: #9ece6a;
box-shadow: 0 0 5px rgba(158, 206, 106, 0.4);
box-shadow: 0 0 5px rgb(158 206 106 / 40%);
}
.terminal-title {
color: #a9b1d6;
position: absolute;
left: 50%;
font-size: 13px;
font-weight: 600;
letter-spacing: 0.8px;
position: absolute;
left: 50%;
color: #a9b1d6;
transform: translateX(-50%);
}
.terminal-copy-btn {
display: flex;
padding: 6px 12px;
font-family: inherit;
font-size: 12px;
color: #a9b1d6;
cursor: pointer;
background: transparent;
border: 1px solid #414868;
color: #a9b1d6;
border-radius: 6px;
padding: 6px 12px;
font-size: 12px;
cursor: pointer;
transition: all 0.25s cubic-bezier(0.175, 0.885, 0.32, 1.275);
display: flex;
align-items: center;
gap: 6px;
font-family: inherit;
}
.terminal-copy-btn:hover {
color: #1a1b26;
background: #bb9af7;
border-color: #bb9af7;
color: #1a1b26;
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(187, 154, 247, 0.3);
box-shadow: 0 4px 12px rgb(187 154 247 / 30%);
}
.terminal-copy-btn:active {
transform: translateY(0);
}
@ -217,17 +223,17 @@ onMounted(() => {
.terminal-body {
padding: 20px;
color: #c0caf5;
font-size: 13px;
line-height: 1.6;
color: #c0caf5;
}
.terminal-desc {
color: #7dcfff;
padding-bottom: 16px;
margin-bottom: 16px;
font-family: var(--el-font-family);
font-size: 13px;
padding-bottom: 16px;
color: #7dcfff;
border-bottom: 1px dashed #292e42;
}
@ -237,9 +243,9 @@ onMounted(() => {
}
.terminal-code {
min-width: max-content;
margin: 0;
white-space: pre;
min-width: max-content;
}
.terminal-code code {
@ -267,13 +273,16 @@ onMounted(() => {
.terminal-code-wrapper::-webkit-scrollbar {
height: 8px;
}
.terminal-code-wrapper::-webkit-scrollbar-thumb {
background: #414868;
border-radius: 4px;
}
.terminal-code-wrapper::-webkit-scrollbar-thumb:hover {
background: #565f89;
}
.terminal-code-wrapper::-webkit-scrollbar-track {
background: transparent;
}

View File

@ -36,7 +36,7 @@
{{ conditionIndex + 1 }}
</div>
<span class="text-12px font-500 text-[var(--el-text-color-primary)]"
>条件 {{ conditionIndex + 1 }}</span
>条件 {{ conditionIndex + 1 }}</span
>
</div>
<el-button

View File

@ -75,7 +75,7 @@
>
<Icon icon="ep:timer" class="text-[var(--el-color-danger)] text-18px" />
<span class="text-14px font-500 text-[var(--el-text-color-primary)]"
>定时触发配置</span
>定时触发配置</span
>
</div>

View File

@ -107,7 +107,7 @@
<div
v-if="
selectedProperty.type === IoTThingModelTypeEnum.PROPERTY &&
selectedProperty.accessMode
selectedProperty.accessMode
"
class="flex items-start gap-8px"
>