Skip to content

Commit 7224777

Browse files
committed
feat: 弹窗 UI 多处优化
无 URL 技术不再显示成可点击链接样式(buildPopupResult 改 async 通过 attachTechnologyLinks 预填 URL,detection/bundle-license 调用方同步加 await)。识别纠正按钮跳转前把完整原始线索复制到剪贴板、issue body 引导粘贴。Select 组件加 clearable + X 重置按钮(默认开启,按钮模式与可输入模式都覆盖)。源代码搜索 / 原始线索面板展开时加遮罩、点击关闭、带 0.2s 渐变动画。弹窗 status 改为与 settings 一致的悬浮 msg 浮动卡片,加 ok/error 类型 + 3 秒自动消失;复制 / 刷新 / 加载完成都给出 ok 提示,错误用 error 提示。顶部"响应头"指标后跟随转圈 Loader2 图标表示后台检测进行中,检测完成自动消失。将版本号提升到 1.2.92。
1 parent f7f1247 commit 7224777

7 files changed

Lines changed: 236 additions & 65 deletions

File tree

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "stackprism",
33
"private": true,
4-
"version": "1.2.91",
4+
"version": "1.2.92",
55
"type": "module",
66
"description": "StackPrism 用于检测网页前端、后端、CDN、SaaS、广告营销、统计、登录、支付、网站程序和主题模板线索。",
77
"scripts": {

src/background/bundle-license.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -375,7 +375,7 @@ const detectTechnologiesFromLicenseText = (observations: ScriptLicenseObservatio
375375

376376
const saveBundleLicenseDataAndBadge = async (tabId: number, data: any, settings: any, tab: any) => {
377377
if (!isDetectablePageUrl(tab?.url)) return
378-
const popup = buildPopupCacheRecord(data, settings, tab)
378+
const popup = await buildPopupCacheRecord(data, settings, tab)
379379
const { popup: _legacyPopup, ...tabData } = data || {}
380380
await writeTabData(tabId, tabData, popup)
381381
await updateBadgeForTab(tabId, popup)

src/background/detection.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ export const saveTabDataAndBadge = async (tabId: number, data: any, settings: an
5858
clearBadge(tabId)
5959
return
6060
}
61-
const popup = buildPopupCacheRecord(data, settings, tab)
61+
const popup = await buildPopupCacheRecord(data, settings, tab)
6262
const { popup: _legacyPopup, ...tabData } = data || {}
6363
await writeTabData(tabId, tabData, popup)
6464
await updateBadgeForTab(tabId, popup)

src/background/popup-cache.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -252,8 +252,8 @@ const buildDisplayTechnologies = (data: any, settings: any) => {
252252
return filterTechnologiesBySettings(suppressGenericCdnFallbacks(mergeDisplayTechnologyRecords(all)), settings)
253253
}
254254

255-
const buildPopupResult = (data: any, settings: any, tab: any) => {
256-
const technologies = buildDisplayTechnologies(data, settings)
255+
const buildPopupResult = async (data: any, settings: any, tab: any) => {
256+
const technologies = await attachTechnologyLinks(buildDisplayTechnologies(data, settings), settings)
257257
const resources = mergeResourceSummary(data.page?.resources || {}, data.dynamic || {})
258258
const main = data.main || {}
259259
const headerCount =
@@ -295,11 +295,11 @@ export const buildPopupRawResult = async (data: any, settings: any, tab: any) =>
295295
}
296296
}
297297

298-
export const buildPopupCacheRecord = (data: any, settings: any, tab: any) => {
298+
export const buildPopupCacheRecord = async (data: any, settings: any, tab: any) => {
299299
const hydrated = addStoredCustomHeaderRules(data || {}, settings)
300300
const sourceUpdatedAt = getStoredUpdatedAt(hydrated)
301301
return {
302-
...buildPopupResult(hydrated, settings, tab),
302+
...(await buildPopupResult(hydrated, settings, tab)),
303303
cacheVersion: POPUP_CACHE_SCHEMA_VERSION,
304304
settingsKey: buildSettingsCacheKey(settings),
305305
hasCache: hasStoredDetection(hydrated),
@@ -338,7 +338,7 @@ export const getPopupResultResponse = async (tabId: number) => {
338338
}
339339

340340
const data = await getTabData(tabId)
341-
const popup = buildPopupCacheRecord(data, settings, tab)
341+
const popup = await buildPopupCacheRecord(data, settings, tab)
342342
if (hasStoredDetection(data)) {
343343
const { popup: legacyPopup, ...tabData } = data || {}
344344
const nextStorage: Record<string, unknown> = { [popupStorageKey(tabId)]: popup }

src/ui/components/Select.vue

Lines changed: 73 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,17 @@
1414
<span :class="['sp-select-value', { placeholder: !selectedLabel }]">
1515
{{ selectedLabel || placeholder || '请选择' }}
1616
</span>
17+
<span
18+
v-if="showClearButton"
19+
class="sp-clear-btn"
20+
role="button"
21+
:title="clearTitle"
22+
:aria-label="clearTitle"
23+
@click.stop="clear"
24+
@mousedown.stop
25+
>
26+
<X :size="12" :stroke-width="2" />
27+
</span>
1728
<ChevronDown class="sp-select-chevron" :class="{ flipped: isOpen }" :size="14" :stroke-width="2" />
1829
</button>
1930

@@ -29,6 +40,17 @@
2940
@focus="open"
3041
@keydown="onKeyDown"
3142
/>
43+
<button
44+
v-if="showClearButton"
45+
type="button"
46+
class="sp-clear-btn-input"
47+
tabindex="-1"
48+
:title="clearTitle"
49+
:aria-label="clearTitle"
50+
@mousedown.prevent="clear"
51+
>
52+
<X :size="12" :stroke-width="2" />
53+
</button>
3254
<button type="button" class="sp-chevron-btn" tabindex="-1" :disabled="disabled" @mousedown.prevent="toggleFromInput">
3355
<ChevronDown class="sp-select-chevron" :class="{ flipped: isOpen }" :size="14" :stroke-width="2" />
3456
</button>
@@ -55,20 +77,28 @@
5577

5678
<script setup lang="ts">
5779
import { ref, computed, onBeforeUnmount, onMounted } from 'vue'
58-
import { Check, ChevronDown } from 'lucide-vue-next'
80+
import { Check, ChevronDown, X } from 'lucide-vue-next'
5981
6082
interface SelectOption {
6183
value: string
6284
label: string
6385
}
6486
65-
const props = defineProps<{
66-
modelValue: string
67-
options: SelectOption[]
68-
placeholder?: string
69-
disabled?: boolean
70-
creatable?: boolean
71-
}>()
87+
const props = withDefaults(
88+
defineProps<{
89+
modelValue: string
90+
options: SelectOption[]
91+
placeholder?: string
92+
disabled?: boolean
93+
creatable?: boolean
94+
clearable?: boolean
95+
clearTitle?: string
96+
}>(),
97+
{
98+
clearable: true,
99+
clearTitle: '清除选择'
100+
}
101+
)
72102
73103
const emit = defineEmits<{
74104
'update:modelValue': [value: string]
@@ -86,6 +116,16 @@
86116
return props.modelValue || ''
87117
})
88118
119+
const showClearButton = computed(() => props.clearable && !props.disabled && Boolean(props.modelValue))
120+
121+
const clear = () => {
122+
if (props.disabled) return
123+
emit('update:modelValue', '')
124+
close()
125+
if (props.creatable) inputRef.value?.focus()
126+
else triggerRef.value?.focus()
127+
}
128+
89129
const filteredOptions = computed(() => {
90130
if (!props.creatable) return props.options
91131
const query = props.modelValue.trim().toLowerCase()
@@ -276,6 +316,31 @@
276316
cursor: not-allowed;
277317
}
278318
319+
.sp-clear-btn,
320+
.sp-clear-btn-input {
321+
align-items: center;
322+
background: transparent;
323+
border: 0;
324+
border-radius: 4px;
325+
color: var(--muted);
326+
cursor: pointer;
327+
display: inline-flex;
328+
flex-shrink: 0;
329+
height: 18px;
330+
justify-content: center;
331+
padding: 0;
332+
transition:
333+
background 0.15s ease,
334+
color 0.15s ease;
335+
width: 18px;
336+
}
337+
338+
.sp-clear-btn:hover,
339+
.sp-clear-btn-input:hover {
340+
background: var(--accent-soft);
341+
color: var(--accent);
342+
}
343+
279344
.sp-select-value {
280345
overflow: hidden;
281346
text-overflow: ellipsis;

0 commit comments

Comments
 (0)