mirror of
https://github.com/fofolee/uTools-quickcommand.git
synced 2025-06-09 15:04:06 +08:00
264 lines
7.2 KiB
Vue
264 lines
7.2 KiB
Vue
<template>
|
||
<q-card style="width: 800px" class="q-pa-sm">
|
||
<div class="text-h5 q-my-md q-px-sm">API配置</div>
|
||
<div>
|
||
<div class="flex q-mb-md q-px-sm" style="height: 26px">
|
||
<ButtonGroup
|
||
v-model="apiToAdd"
|
||
class="col"
|
||
:options="[
|
||
{ label: 'OPENAI', value: 'openai' },
|
||
{ label: 'OLLAMA', value: 'ollama' },
|
||
]"
|
||
height="26px"
|
||
/>
|
||
<q-icon
|
||
name="add_box"
|
||
@click="addModel"
|
||
color="primary"
|
||
size="26px"
|
||
class="cursor-pointer q-ml-sm"
|
||
/>
|
||
</div>
|
||
<q-scroll-area
|
||
:style="`height: ${getConfigListHeight()}px;`"
|
||
class="q-px-sm"
|
||
:vertical-thumb-style="{
|
||
width: '2px',
|
||
}"
|
||
>
|
||
<draggable
|
||
v-model="aiConfigs"
|
||
item-key="id"
|
||
handle=".drag-handle"
|
||
:animation="200"
|
||
class="config-list"
|
||
>
|
||
<template #item="{ element: aiConfig, index }">
|
||
<div class="config-item">
|
||
<div class="config-item-side-bar">
|
||
<q-icon
|
||
name="drag_indicator"
|
||
class="drag-handle cursor-move"
|
||
size="20px"
|
||
/>
|
||
</div>
|
||
<div class="config-item-content">
|
||
<div class="row q-col-gutter-sm">
|
||
<q-input
|
||
filled
|
||
dense
|
||
v-model="aiConfig.name"
|
||
class="col"
|
||
placeholder="请输入名称"
|
||
>
|
||
<template v-slot:prepend>
|
||
<q-badge
|
||
color="primary"
|
||
text-color="white"
|
||
label="名称"
|
||
class="q-pa-xs"
|
||
/>
|
||
</template>
|
||
<template v-slot:append>
|
||
<q-icon
|
||
color="grey"
|
||
name="remove_circle"
|
||
@click="deleteModel(index)"
|
||
size="16px"
|
||
class="cursor-pointer"
|
||
/>
|
||
</template>
|
||
</q-input>
|
||
<q-input
|
||
filled
|
||
dense
|
||
v-model="aiConfig.apiUrl"
|
||
class="col-7"
|
||
:placeholder="
|
||
aiConfig.apiType === 'openai'
|
||
? '例:https://api.openai.com'
|
||
: '例:http://localhost:11434'
|
||
"
|
||
>
|
||
<template v-slot:prepend>
|
||
<q-badge
|
||
color="primary"
|
||
text-color="white"
|
||
label="接口"
|
||
class="q-pa-xs"
|
||
/>
|
||
</template>
|
||
</q-input>
|
||
</div>
|
||
<div class="row q-col-gutter-sm">
|
||
<q-input filled dense v-model="aiConfig.model" class="col">
|
||
<template v-slot:prepend>
|
||
<q-badge
|
||
color="primary"
|
||
text-color="white"
|
||
label="模型"
|
||
class="q-pa-xs"
|
||
/>
|
||
</template>
|
||
<template v-slot:append>
|
||
<q-btn-dropdown
|
||
flat
|
||
@click="getModels(aiConfig)"
|
||
dense
|
||
dropdown-icon="refresh"
|
||
>
|
||
<q-list dense>
|
||
<q-item
|
||
v-for="model in models"
|
||
:key="model"
|
||
clickable
|
||
v-close-popup
|
||
@click="aiConfig.model = model"
|
||
>
|
||
<q-item-section>
|
||
{{ model }}
|
||
</q-item-section>
|
||
</q-item>
|
||
</q-list>
|
||
</q-btn-dropdown>
|
||
<q-tooltip>获取模型</q-tooltip>
|
||
</template>
|
||
</q-input>
|
||
<q-input
|
||
filled
|
||
dense
|
||
v-model="aiConfig.apiToken"
|
||
v-if="aiConfig.apiType === 'openai'"
|
||
type="password"
|
||
class="col-7"
|
||
>
|
||
<template v-slot:prepend>
|
||
<q-badge
|
||
color="primary"
|
||
text-color="white"
|
||
label="令牌"
|
||
class="q-pa-xs"
|
||
/>
|
||
</template>
|
||
</q-input>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
</draggable>
|
||
</q-scroll-area>
|
||
</div>
|
||
<div class="flex justify-end q-gutter-sm q-px-sm">
|
||
<q-btn flat color="grey" label="取消" v-close-popup />
|
||
<q-btn
|
||
flat
|
||
color="primary"
|
||
label="保存"
|
||
v-close-popup
|
||
@click="saveConfig"
|
||
/>
|
||
</div>
|
||
</q-card>
|
||
</template>
|
||
|
||
<script>
|
||
import { defineComponent } from "vue";
|
||
import { dbManager } from "js/utools.js";
|
||
import ButtonGroup from "components/composer/common/ButtonGroup.vue";
|
||
import draggable from "vuedraggable";
|
||
import { getUniqueId } from "js/common/uuid.js";
|
||
|
||
export default defineComponent({
|
||
name: "AIConfig",
|
||
components: {
|
||
ButtonGroup,
|
||
draggable,
|
||
},
|
||
data() {
|
||
return {
|
||
apiToAdd: "openai",
|
||
aiConfigs: [],
|
||
models: [],
|
||
};
|
||
},
|
||
emits: ["save"],
|
||
methods: {
|
||
async getModels(aiConfig) {
|
||
const { success, result, error } = await window.getModelsFromAiApi(
|
||
aiConfig
|
||
);
|
||
if (!success) {
|
||
quickcommand.showMessageBox(error, "error");
|
||
this.models = [];
|
||
return;
|
||
}
|
||
this.models = result;
|
||
},
|
||
saveConfig() {
|
||
dbManager.setStorage(
|
||
"cfg_aiConfigs",
|
||
window.lodashM.cloneDeep(this.aiConfigs)
|
||
);
|
||
this.$emit("save");
|
||
},
|
||
deleteModel(index) {
|
||
this.aiConfigs.splice(index, 1);
|
||
},
|
||
addModel() {
|
||
this.aiConfigs.push({
|
||
id: getUniqueId(),
|
||
apiType: this.apiToAdd,
|
||
apiUrl: "",
|
||
apiToken: "",
|
||
model: "",
|
||
name: "",
|
||
});
|
||
},
|
||
getConfigListHeight() {
|
||
const counts = Math.min(this.aiConfigs.length, 3);
|
||
return counts * 100 + (counts - 1) * 8;
|
||
},
|
||
},
|
||
mounted() {
|
||
this.aiConfigs = (dbManager.getStorage("cfg_aiConfigs") || []).map(
|
||
(config) => ({
|
||
...config,
|
||
id: config.id || getUniqueId(),
|
||
})
|
||
);
|
||
},
|
||
});
|
||
</script>
|
||
|
||
<style scoped>
|
||
.config-list,
|
||
.config-item-content {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 8px;
|
||
}
|
||
|
||
.config-item {
|
||
border: 1px solid var(--q-primary);
|
||
border-radius: 4px;
|
||
padding: 8px;
|
||
display: flex;
|
||
}
|
||
|
||
.config-item-side-bar {
|
||
width: 20px;
|
||
padding-top: 8px;
|
||
}
|
||
|
||
.config-item-content {
|
||
flex: 1;
|
||
}
|
||
|
||
.drag-handle {
|
||
cursor: move;
|
||
color: var(--q-primary);
|
||
margin-right: 4px;
|
||
}
|
||
</style>
|