feat: 添加支持 modelscope 安装的说明
This commit is contained in:
parent
fafbc5c9ee
commit
e94d293737
@ -294,71 +294,87 @@
|
|||||||
<a href="https://skills.sh/" target="_blank" rel="noopener noreferrer"
|
<a href="https://skills.sh/" target="_blank" rel="noopener noreferrer"
|
||||||
>skills.sh</a
|
>skills.sh</a
|
||||||
>
|
>
|
||||||
查询开源 skills。
|
查询开源 skills。 也支持 ModelScope 单个 Skill
|
||||||
|
地址,每次仅限安装一个:`https://modelscope.cn/skills/<skill-id>`。 Skill
|
||||||
|
ID 可在
|
||||||
|
<a href="https://modelscope.cn/skills" target="_blank" rel="noopener noreferrer"
|
||||||
|
>ModelScope Skill 市场</a
|
||||||
|
>
|
||||||
|
进入详情后从地址栏获取。
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 仓库技能分页多选列表 -->
|
<!-- 仓库技能分页多选列表 -->
|
||||||
<div v-if="remoteSkillOptions.length" class="skills-list-section">
|
<div v-if="remoteSkillOptions.length" class="skills-list-section">
|
||||||
<div class="list-operations-bar">
|
<template v-if="hasSingleRepoSkill">
|
||||||
<div class="op-buttons">
|
<div class="single-remote-skill-card">
|
||||||
<a-button size="small" type="link" @click="handleRepoSelectAll"
|
<div class="single-remote-skill-name">{{ singleRepoSkill.name }}</div>
|
||||||
>全选</a-button
|
<div class="single-remote-skill-meta">
|
||||||
>
|
{{ singleRepoSkill.description || '暂无描述' }}
|
||||||
<a-button size="small" type="link" @click="handleRepoSelectInvert"
|
</div>
|
||||||
>反选</a-button
|
|
||||||
>
|
|
||||||
<a-button size="small" type="link" @click="handleRepoSelectNone"
|
|
||||||
>清空</a-button
|
|
||||||
>
|
|
||||||
</div>
|
</div>
|
||||||
<a-input
|
</template>
|
||||||
v-model:value="repoFilterKeyword"
|
<template v-else>
|
||||||
placeholder="本地过滤检索..."
|
<div class="list-operations-bar">
|
||||||
size="small"
|
<div class="op-buttons">
|
||||||
style="width: 180px"
|
<a-button size="small" type="link" @click="handleRepoSelectAll"
|
||||||
allow-clear
|
>全选</a-button
|
||||||
/>
|
>
|
||||||
</div>
|
<a-button size="small" type="link" @click="handleRepoSelectInvert"
|
||||||
<div class="skills-list-viewport">
|
>反选</a-button
|
||||||
<a-list
|
>
|
||||||
size="small"
|
<a-button size="small" type="link" @click="handleRepoSelectNone"
|
||||||
:pagination="{ pageSize: 5, size: 'small', showSizeChanger: false }"
|
>清空</a-button
|
||||||
:data-source="filteredRepoSkills"
|
>
|
||||||
class="remote-skills-list-container"
|
</div>
|
||||||
>
|
<a-input
|
||||||
<template #renderItem="{ item }">
|
v-model:value="repoFilterKeyword"
|
||||||
<a-list-item>
|
placeholder="本地过滤检索..."
|
||||||
<div class="skill-list-item-content">
|
size="small"
|
||||||
<div class="skill-name-col">
|
style="width: 180px"
|
||||||
<a-checkbox
|
allow-clear
|
||||||
:checked="selectedRepoSkills.includes(item.name)"
|
/>
|
||||||
@change="
|
</div>
|
||||||
(e) => handleToggleRepoSkill(item.name, e.target.checked)
|
<div class="skills-list-viewport">
|
||||||
"
|
<a-list
|
||||||
:disabled="installingRemoteSkill"
|
size="small"
|
||||||
>
|
:pagination="{ pageSize: 5, size: 'small', showSizeChanger: false }"
|
||||||
<span class="skill-item-name">{{ item.name }}</span>
|
:data-source="filteredRepoSkills"
|
||||||
</a-checkbox>
|
class="remote-skills-list-container"
|
||||||
|
>
|
||||||
|
<template #renderItem="{ item }">
|
||||||
|
<a-list-item>
|
||||||
|
<div class="skill-list-item-content">
|
||||||
|
<div class="skill-name-col">
|
||||||
|
<a-checkbox
|
||||||
|
:checked="selectedRepoSkills.includes(item.name)"
|
||||||
|
@change="
|
||||||
|
(e) => handleToggleRepoSkill(item.name, e.target.checked)
|
||||||
|
"
|
||||||
|
:disabled="installingRemoteSkill"
|
||||||
|
>
|
||||||
|
<span class="skill-item-name">{{ item.name }}</span>
|
||||||
|
</a-checkbox>
|
||||||
|
</div>
|
||||||
|
<div class="skill-desc-col">
|
||||||
|
<a-tooltip
|
||||||
|
:title="item.description || '暂无描述'"
|
||||||
|
placement="topLeft"
|
||||||
|
>
|
||||||
|
<span class="skill-item-desc">{{
|
||||||
|
item.description || '暂无描述'
|
||||||
|
}}</span>
|
||||||
|
</a-tooltip>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="skill-desc-col">
|
</a-list-item>
|
||||||
<a-tooltip
|
</template>
|
||||||
:title="item.description || '暂无描述'"
|
</a-list>
|
||||||
placement="topLeft"
|
</div>
|
||||||
>
|
<div class="remote-skill-summary">
|
||||||
<span class="skill-item-desc">{{
|
已选 {{ selectedRepoSkills.length }} / 共发现
|
||||||
item.description || '暂无描述'
|
{{ remoteSkillOptions.length }} 个 skills。
|
||||||
}}</span>
|
</div>
|
||||||
</a-tooltip>
|
</template>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</a-list-item>
|
|
||||||
</template>
|
|
||||||
</a-list>
|
|
||||||
</div>
|
|
||||||
<div class="remote-skill-summary">
|
|
||||||
已选 {{ selectedRepoSkills.length }} / 共发现
|
|
||||||
{{ remoteSkillOptions.length }} 个 skills。
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</a-form>
|
</a-form>
|
||||||
</div>
|
</div>
|
||||||
@ -392,65 +408,86 @@
|
|||||||
|
|
||||||
<!-- 搜索结果列表 -->
|
<!-- 搜索结果列表 -->
|
||||||
<div v-if="searchedSkills.length" class="skills-list-section">
|
<div v-if="searchedSkills.length" class="skills-list-section">
|
||||||
<div class="list-operations-bar">
|
<template v-if="hasSingleSearchedSkill">
|
||||||
<div class="op-buttons">
|
<div class="single-remote-skill-card">
|
||||||
<a-button size="small" type="link" @click="handleSearchSelectAll"
|
<div class="single-remote-skill-header">
|
||||||
>全选</a-button
|
<div class="single-remote-skill-name">
|
||||||
>
|
{{ singleSearchedSkill.name }}
|
||||||
<a-button size="small" type="link" @click="handleSearchSelectInvert"
|
</div>
|
||||||
>反选</a-button
|
<a-tag
|
||||||
>
|
v-if="singleSearchedSkill.installs"
|
||||||
<a-button size="small" type="link" @click="handleSearchSelectNone"
|
color="blue"
|
||||||
>清空</a-button
|
class="skill-item-installs"
|
||||||
>
|
>
|
||||||
|
{{ singleSearchedSkill.installs }}
|
||||||
|
</a-tag>
|
||||||
|
</div>
|
||||||
|
<div class="single-remote-skill-meta">
|
||||||
|
{{ singleSearchedSkill.source }}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</template>
|
||||||
<div class="skills-list-viewport">
|
<template v-else>
|
||||||
<a-list
|
<div class="list-operations-bar">
|
||||||
size="small"
|
<div class="op-buttons">
|
||||||
:pagination="{ pageSize: 5, size: 'small', showSizeChanger: false }"
|
<a-button size="small" type="link" @click="handleSearchSelectAll"
|
||||||
:data-source="searchedSkills"
|
>全选</a-button
|
||||||
class="remote-skills-list-container"
|
>
|
||||||
>
|
<a-button size="small" type="link" @click="handleSearchSelectInvert"
|
||||||
<template #renderItem="{ item }">
|
>反选</a-button
|
||||||
<a-list-item>
|
>
|
||||||
<div class="search-skill-item-row">
|
<a-button size="small" type="link" @click="handleSearchSelectNone"
|
||||||
<div class="skill-name-col">
|
>清空</a-button
|
||||||
<a-checkbox
|
>
|
||||||
:checked="
|
</div>
|
||||||
selectedSearchSkills.some(
|
</div>
|
||||||
(s) => s.name === item.name && s.source === item.source
|
<div class="skills-list-viewport">
|
||||||
)
|
<a-list
|
||||||
"
|
size="small"
|
||||||
@change="(e) => handleToggleSearchSkill(item, e.target.checked)"
|
:pagination="{ pageSize: 5, size: 'small', showSizeChanger: false }"
|
||||||
:disabled="installingRemoteSkill"
|
:data-source="searchedSkills"
|
||||||
>
|
class="remote-skills-list-container"
|
||||||
<span class="skill-item-name">{{ item.name }}</span>
|
>
|
||||||
</a-checkbox>
|
<template #renderItem="{ item }">
|
||||||
|
<a-list-item>
|
||||||
|
<div class="search-skill-item-row">
|
||||||
|
<div class="skill-name-col">
|
||||||
|
<a-checkbox
|
||||||
|
:checked="
|
||||||
|
selectedSearchSkills.some(
|
||||||
|
(s) => s.name === item.name && s.source === item.source
|
||||||
|
)
|
||||||
|
"
|
||||||
|
@change="(e) => handleToggleSearchSkill(item, e.target.checked)"
|
||||||
|
:disabled="installingRemoteSkill"
|
||||||
|
>
|
||||||
|
<span class="skill-item-name">{{ item.name }}</span>
|
||||||
|
</a-checkbox>
|
||||||
|
</div>
|
||||||
|
<div class="skill-repo-col">
|
||||||
|
<a-tooltip :title="item.source" placement="topLeft">
|
||||||
|
<span class="skill-item-repo">{{ item.source }}</span>
|
||||||
|
</a-tooltip>
|
||||||
|
</div>
|
||||||
|
<div class="skill-install-col">
|
||||||
|
<a-tag
|
||||||
|
v-if="item.installs"
|
||||||
|
color="blue"
|
||||||
|
class="skill-item-installs"
|
||||||
|
>
|
||||||
|
{{ item.installs }}
|
||||||
|
</a-tag>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="skill-repo-col">
|
</a-list-item>
|
||||||
<a-tooltip :title="item.source" placement="topLeft">
|
</template>
|
||||||
<span class="skill-item-repo">{{ item.source }}</span>
|
</a-list>
|
||||||
</a-tooltip>
|
</div>
|
||||||
</div>
|
<div class="remote-skill-summary">
|
||||||
<div class="skill-install-col">
|
已选择 {{ selectedSearchSkills.length }} / 共找到
|
||||||
<a-tag
|
{{ searchedSkills.length }} 个 skills。
|
||||||
v-if="item.installs"
|
</div>
|
||||||
color="blue"
|
</template>
|
||||||
class="skill-item-installs"
|
|
||||||
>
|
|
||||||
{{ item.installs }}
|
|
||||||
</a-tag>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</a-list-item>
|
|
||||||
</template>
|
|
||||||
</a-list>
|
|
||||||
</div>
|
|
||||||
<div class="remote-skill-summary">
|
|
||||||
已选择 {{ selectedSearchSkills.length }} / 共找到
|
|
||||||
{{ searchedSkills.length }} 个 skills。
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</a-form>
|
</a-form>
|
||||||
</div>
|
</div>
|
||||||
@ -587,11 +624,15 @@ const remoteInstallForm = reactive({
|
|||||||
const remoteSkillOptions = ref([])
|
const remoteSkillOptions = ref([])
|
||||||
const repoFilterKeyword = ref('')
|
const repoFilterKeyword = ref('')
|
||||||
const selectedRepoSkills = ref([])
|
const selectedRepoSkills = ref([])
|
||||||
|
const hasSingleRepoSkill = computed(() => remoteSkillOptions.value.length === 1)
|
||||||
|
const singleRepoSkill = computed(() => remoteSkillOptions.value[0] || null)
|
||||||
|
|
||||||
const searchKeyword = ref('')
|
const searchKeyword = ref('')
|
||||||
const searchingRemoteSkills = ref(false)
|
const searchingRemoteSkills = ref(false)
|
||||||
const searchedSkills = ref([])
|
const searchedSkills = ref([])
|
||||||
const selectedSearchSkills = ref([])
|
const selectedSearchSkills = ref([])
|
||||||
|
const hasSingleSearchedSkill = computed(() => searchedSkills.value.length === 1)
|
||||||
|
const singleSearchedSkill = computed(() => searchedSkills.value[0] || null)
|
||||||
|
|
||||||
const repoHistory = ref([])
|
const repoHistory = ref([])
|
||||||
const allowedSkillAccessLevels = ref(['user'])
|
const allowedSkillAccessLevels = ref(['user'])
|
||||||
@ -1049,12 +1090,17 @@ const handleListRemoteSkills = async () => {
|
|||||||
try {
|
try {
|
||||||
const result = await skillApi.listRemoteSkills(source)
|
const result = await skillApi.listRemoteSkills(source)
|
||||||
remoteSkillOptions.value = result?.data || []
|
remoteSkillOptions.value = result?.data || []
|
||||||
selectedRepoSkills.value = []
|
selectedRepoSkills.value =
|
||||||
|
remoteSkillOptions.value.length === 1 ? [remoteSkillOptions.value[0].name] : []
|
||||||
if (!remoteSkillOptions.value.length) {
|
if (!remoteSkillOptions.value.length) {
|
||||||
message.warning('未发现可安装的 Skills')
|
message.warning('未发现可安装的 Skills')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
message.success(`已发现 ${remoteSkillOptions.value.length} 个 Skills`)
|
if (remoteSkillOptions.value.length === 1) {
|
||||||
|
message.success('已发现 1 个 Skill,已自动选中')
|
||||||
|
} else {
|
||||||
|
message.success(`已发现 ${remoteSkillOptions.value.length} 个 Skills`)
|
||||||
|
}
|
||||||
|
|
||||||
// 保存成功的拉取历史
|
// 保存成功的拉取历史
|
||||||
let history = [...repoHistory.value]
|
let history = [...repoHistory.value]
|
||||||
@ -1112,9 +1158,11 @@ const handleSearchRemoteSkills = async () => {
|
|||||||
try {
|
try {
|
||||||
const result = await skillApi.searchRemoteSkills(query)
|
const result = await skillApi.searchRemoteSkills(query)
|
||||||
searchedSkills.value = result?.data || []
|
searchedSkills.value = result?.data || []
|
||||||
selectedSearchSkills.value = []
|
selectedSearchSkills.value = searchedSkills.value.length === 1 ? [...searchedSkills.value] : []
|
||||||
if (!searchedSkills.value.length) {
|
if (!searchedSkills.value.length) {
|
||||||
message.warning('未搜索到相关的 Skills')
|
message.warning('未搜索到相关的 Skills')
|
||||||
|
} else if (searchedSkills.value.length === 1) {
|
||||||
|
message.success('搜索到 1 个 Skill,已自动选中')
|
||||||
} else {
|
} else {
|
||||||
message.success(`搜索到 ${searchedSkills.value.length} 个 Skills`)
|
message.success(`搜索到 ${searchedSkills.value.length} 个 Skills`)
|
||||||
}
|
}
|
||||||
@ -1627,6 +1675,45 @@ defineExpose({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.single-remote-skill-card {
|
||||||
|
border: 1px solid var(--gray-150);
|
||||||
|
border-radius: 6px;
|
||||||
|
background: var(--gray-0);
|
||||||
|
padding: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.single-remote-skill-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 12px;
|
||||||
|
min-width: 0;
|
||||||
|
|
||||||
|
.ant-tag {
|
||||||
|
flex-shrink: 0;
|
||||||
|
margin-inline-end: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.single-remote-skill-name {
|
||||||
|
line-height: 20px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--gray-900);
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
.single-remote-skill-meta {
|
||||||
|
margin-top: 2px;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 18px;
|
||||||
|
color: var(--gray-500);
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
.skill-list-item-content {
|
.skill-list-item-content {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|||||||
@ -283,7 +283,7 @@ const normalizedTags = computed(() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
&-mini {
|
&-mini {
|
||||||
padding: 12px 14px;
|
padding: 16px 14px;
|
||||||
gap: 0;
|
gap: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user