mirror of
https://github.com/1Panel-dev/MaxKB.git
synced 2025-12-26 01:33:05 +00:00
Merge branch 'main' of github.com:maxkb-dev/maxkb
This commit is contained in:
commit
d5b924b63e
|
|
@ -1,9 +1,9 @@
|
|||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<link rel="icon" href="/favicon.ico">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>%VITE_APP_TITLE%</title>
|
||||
</head>
|
||||
<body>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,66 @@
|
|||
// async function embedChatbot() {
|
||||
// const t = window.difyChatbotConfig
|
||||
// if (t && t.token) {
|
||||
// var e = !!t.isDev
|
||||
// const o = t.baseUrl || `https://${e ? 'dev.' : ''}udify.app`,
|
||||
// n = `<svg
|
||||
// id="openIcon"
|
||||
// width="24"
|
||||
// height="24"
|
||||
// viewBox="0 0 24 24"
|
||||
// fill="none"
|
||||
// xmlns="http://www.w3.org/2000/svg"
|
||||
// >
|
||||
// <path
|
||||
// fill-rule="evenodd"
|
||||
// clip-rule="evenodd"
|
||||
// d="M7.7586 2L16.2412 2C17.0462 1.99999 17.7105 1.99998 18.2517 2.04419C18.8138 2.09012 19.3305 2.18868 19.8159 2.43598C20.5685 2.81947 21.1804 3.43139 21.5639 4.18404C21.8112 4.66937 21.9098 5.18608 21.9557 5.74818C21.9999 6.28937 21.9999 6.95373 21.9999 7.7587L22 14.1376C22.0004 14.933 22.0007 15.5236 21.8636 16.0353C21.4937 17.4156 20.4155 18.4938 19.0352 18.8637C18.7277 18.9461 18.3917 18.9789 17.9999 18.9918L17.9999 20.371C18 20.6062 18 20.846 17.9822 21.0425C17.9651 21.2305 17.9199 21.5852 17.6722 21.8955C17.3872 22.2525 16.9551 22.4602 16.4983 22.4597C16.1013 22.4593 15.7961 22.273 15.6386 22.1689C15.474 22.06 15.2868 21.9102 15.1031 21.7632L12.69 19.8327C12.1714 19.4178 12.0174 19.3007 11.8575 19.219C11.697 19.137 11.5262 19.0771 11.3496 19.0408C11.1737 19.0047 10.9803 19 10.3162 19H7.75858C6.95362 19 6.28927 19 5.74808 18.9558C5.18598 18.9099 4.66928 18.8113 4.18394 18.564C3.43129 18.1805 2.81937 17.5686 2.43588 16.816C2.18859 16.3306 2.09002 15.8139 2.0441 15.2518C1.99988 14.7106 1.99989 14.0463 1.9999 13.2413V7.75868C1.99989 6.95372 1.99988 6.28936 2.0441 5.74818C2.09002 5.18608 2.18859 4.66937 2.43588 4.18404C2.81937 3.43139 3.43129 2.81947 4.18394 2.43598C4.66928 2.18868 5.18598 2.09012 5.74808 2.04419C6.28927 1.99998 6.95364 1.99999 7.7586 2ZM10.5073 7.5C10.5073 6.67157 9.83575 6 9.00732 6C8.1789 6 7.50732 6.67157 7.50732 7.5C7.50732 8.32843 8.1789 9 9.00732 9C9.83575 9 10.5073 8.32843 10.5073 7.5ZM16.6073 11.7001C16.1669 11.3697 15.5426 11.4577 15.2105 11.8959C15.1488 11.9746 15.081 12.0486 15.0119 12.1207C14.8646 12.2744 14.6432 12.4829 14.3566 12.6913C13.7796 13.111 12.9818 13.5001 12.0073 13.5001C11.0328 13.5001 10.235 13.111 9.65799 12.6913C9.37138 12.4829 9.15004 12.2744 9.00274 12.1207C8.93366 12.0486 8.86581 11.9745 8.80418 11.8959C8.472 11.4577 7.84775 11.3697 7.40732 11.7001C6.96549 12.0314 6.87595 12.6582 7.20732 13.1001C7.20479 13.0968 7.21072 13.1043 7.22094 13.1171C7.24532 13.1478 7.29407 13.2091 7.31068 13.2289C7.36932 13.2987 7.45232 13.3934 7.55877 13.5045C7.77084 13.7258 8.08075 14.0172 8.48165 14.3088C9.27958 14.8891 10.4818 15.5001 12.0073 15.5001C13.5328 15.5001 14.735 14.8891 15.533 14.3088C15.9339 14.0172 16.2438 13.7258 16.4559 13.5045C16.5623 13.3934 16.6453 13.2987 16.704 13.2289C16.7333 13.1939 16.7567 13.165 16.7739 13.1432C17.1193 12.6969 17.0729 12.0493 16.6073 11.7001ZM15.0073 6C15.8358 6 16.5073 6.67157 16.5073 7.5C16.5073 8.32843 15.8358 9 15.0073 9C14.1789 9 13.5073 8.32843 13.5073 7.5C13.5073 6.67157 14.1789 6 15.0073 6Z"
|
||||
// fill="white"
|
||||
// />
|
||||
// </svg>`,
|
||||
// i = `<svg
|
||||
// id="closeIcon"
|
||||
// width="24"
|
||||
// height="24"
|
||||
// viewBox="0 0 24 24"
|
||||
// fill="none"
|
||||
// xmlns="http://www.w3.org/2000/svg"
|
||||
// >
|
||||
// <path
|
||||
// d="M18 18L6 6M6 18L18 6"
|
||||
// stroke="white"
|
||||
// stroke-width="2"
|
||||
// stroke-linecap="round"
|
||||
// stroke-linejoin="round"
|
||||
// />
|
||||
// </svg>`
|
||||
// if (!document.getElementById('dify-chatbot-bubble-button')) {
|
||||
// e = document.createElement('div')
|
||||
// ;(e.id = 'dify-chatbot-bubble-button'),
|
||||
// (e.style.cssText =
|
||||
// 'position: fixed; bottom: 1rem; right: 1rem; width: 50px; height: 50px; border-radius: 25px; background-color: #155EEF; box-shadow: rgba(0, 0, 0, 0.2) 0px 4px 8px 0px; cursor: pointer; z-index: 2147483647; transition: all 0.2s ease-in-out 0s; left: unset; transform: scale(1); :hover {transform: scale(1.1);}')
|
||||
// const d = document.createElement('div')
|
||||
// ;(d.style.cssText =
|
||||
// 'display: flex; align-items: center; justify-content: center; width: 100%; height: 100%; z-index: 2147483647;'),
|
||||
// (d.innerHTML = n),
|
||||
// e.appendChild(d),
|
||||
// document.body.appendChild(e),
|
||||
// e.addEventListener('click', function () {
|
||||
// var e = document.getElementById('dify-chatbot-bubble-window')
|
||||
// e
|
||||
// ? 'none' === e.style.display
|
||||
// ? ((e.style.display = 'block'), (d.innerHTML = i))
|
||||
// : ((e.style.display = 'none'), (d.innerHTML = n))
|
||||
// : (((e = document.createElement('iframe')).allow = 'fullscreen;microphone'),
|
||||
// (e.title = 'dify chatbot bubble window'),
|
||||
// (e.id = 'dify-chatbot-bubble-window'),
|
||||
// (e.src = o + '/chatbot/' + t.token),
|
||||
// (e.style.cssText =
|
||||
// 'border: none; position: fixed; flex-direction: column; justify-content: space-between; box-shadow: rgba(150, 150, 150, 0.2) 0px 10px 30px 0px, rgba(150, 150, 150, 0.2) 0px 0px 0px 1px; bottom: 5rem; right: 1rem; width: 24rem; max-width: calc(100vw - 2rem); height: 40rem; max-height: calc(100vh - 6rem);border-radius: 0.75rem; display: flex; z-index: 2147483647; overflow: hidden; left: unset; background-color: #F3F4F6;'),
|
||||
// document.body.appendChild(e),
|
||||
// (d.innerHTML = i))
|
||||
// })
|
||||
// }
|
||||
// } else console.error('difyChatbotConfig is empty or token is not provided')
|
||||
// }
|
||||
// document.body.onload = embedChatbot
|
||||
|
|
@ -72,14 +72,100 @@ const postChatMessage: (chat_id: string, message: string) => Promise<any> = (cha
|
|||
]
|
||||
}
|
||||
*/
|
||||
const postApplication: ( data: ApplicationFormType, loading?: Ref<boolean> ) => Promise<Result<any>> = (data, loading) => {
|
||||
const postApplication: (
|
||||
data: ApplicationFormType,
|
||||
loading?: Ref<boolean>
|
||||
) => Promise<Result<any>> = (data, loading) => {
|
||||
return post(`${prefix}`, data, undefined, loading)
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改应用
|
||||
* @param 参数
|
||||
* {
|
||||
"name": "string",
|
||||
"desc": "string",
|
||||
"model_id": "string",
|
||||
"multiple_rounds_dialogue": true,
|
||||
"prologue": "string",
|
||||
"example": [
|
||||
"string"
|
||||
],
|
||||
"dataset_id_list": [
|
||||
"string"
|
||||
]
|
||||
}
|
||||
*/
|
||||
const putApplication: (
|
||||
applicaiton_id: String,
|
||||
data: ApplicationFormType,
|
||||
loading?: Ref<boolean>
|
||||
) => Promise<Result<any>> = (applicaiton_id, data, loading) => {
|
||||
return put(`${prefix}/${applicaiton_id}`, data, undefined, loading)
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除应用
|
||||
* @param 参数 applicaiton_id
|
||||
*/
|
||||
const delApplication: (applicaiton_id: String) => Promise<Result<boolean>> = (applicaiton_id) => {
|
||||
return del(`${prefix}/${applicaiton_id}`)
|
||||
}
|
||||
|
||||
/**
|
||||
* 应用详情
|
||||
* @param 参数 applicaiton_id
|
||||
*/
|
||||
const getApplicationDetail: (
|
||||
applicaiton_id: string,
|
||||
loading?: Ref<boolean>
|
||||
) => Promise<Result<any>> = (applicaiton_id, loading) => {
|
||||
return get(`${prefix}/${applicaiton_id}`, undefined, loading)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得当前应用可使用的数据集
|
||||
* @param 参数 applicaiton_id
|
||||
*/
|
||||
const getApplicationDataset: (
|
||||
applicaiton_id: string,
|
||||
loading?: Ref<boolean>
|
||||
) => Promise<Result<any>> = (applicaiton_id, loading) => {
|
||||
return get(`${prefix}/${applicaiton_id}/list_dataset`, undefined, loading)
|
||||
}
|
||||
|
||||
/**
|
||||
* API_KEY列表
|
||||
* @param 参数 applicaiton_id
|
||||
*/
|
||||
const getAPIKey: (applicaiton_id: string, loading?: Ref<boolean>) => Promise<Result<any>> = (
|
||||
applicaiton_id,
|
||||
loading
|
||||
) => {
|
||||
return get(`${prefix}/${applicaiton_id}/api_key`, undefined, loading)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取AccessToken
|
||||
* @param 参数 applicaiton_id
|
||||
*/
|
||||
const getAccessToken: (applicaiton_id: string, loading?: Ref<boolean>) => Promise<Result<any>> = (
|
||||
applicaiton_id,
|
||||
loading
|
||||
) => {
|
||||
return get(`${prefix}/${applicaiton_id}/access-token`, undefined, loading)
|
||||
}
|
||||
|
||||
export default {
|
||||
getAllAppilcation,
|
||||
getApplication,
|
||||
postApplication,
|
||||
putApplication,
|
||||
postChatOpen,
|
||||
postChatMessage
|
||||
postChatMessage,
|
||||
delApplication,
|
||||
getApplicationDetail,
|
||||
getApplicationDataset,
|
||||
getAPIKey,
|
||||
getAccessToken
|
||||
}
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 24 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
|
|
@ -55,12 +55,13 @@
|
|||
</AppAvatar>
|
||||
</div>
|
||||
<div class="content">
|
||||
<div class="flex" v-if="!item.answer_text || item.problem_text.length === 0">
|
||||
<el-card shadow="always" class="dialog-card"> {{ '回答中...' }} </el-card>
|
||||
<div class="flex" v-if="!item.answer_text">
|
||||
<el-card shadow="always" class="dialog-card"> 回答中... </el-card>
|
||||
</div>
|
||||
<el-card v-else shadow="always" class="dialog-card">
|
||||
<MarkdownRenderer :source="item.answer_text"></MarkdownRenderer>
|
||||
</el-card>
|
||||
<el-button type="primary" link class="mt-8">停止回答</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -77,22 +78,9 @@
|
|||
:disabled="loading"
|
||||
/>
|
||||
<div class="operate" v-loading="loading">
|
||||
<el-button
|
||||
text
|
||||
class="sent-button"
|
||||
:disabled="!(inputValue && data?.name && data?.model_id)"
|
||||
@click="sendChatHandle"
|
||||
>
|
||||
<img
|
||||
v-show="!(inputValue && data?.name && data?.model_id)"
|
||||
src="@/assets/icon_send.svg"
|
||||
alt=""
|
||||
/>
|
||||
<img
|
||||
v-show="inputValue && data?.name && data?.model_id"
|
||||
src="@/assets/icon_send_colorful.svg"
|
||||
alt=""
|
||||
/>
|
||||
<el-button text class="sent-button" :disabled="isDisabledChart" @click="sendChatHandle">
|
||||
<img v-show="isDisabledChart" src="@/assets/icon_send.svg" alt="" />
|
||||
<img v-show="!isDisabledChart" src="@/assets/icon_send_colorful.svg" alt="" />
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -100,11 +88,10 @@
|
|||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, nextTick, onUpdated } from 'vue'
|
||||
import { ref, nextTick, onUpdated, computed } from 'vue'
|
||||
import applicationApi from '@/api/application'
|
||||
import { ChatManage, type chatType } from '@/api/type/application'
|
||||
import { randomId } from '@/utils/utils'
|
||||
import MarkdownRenderer from '@/components/markdown-renderer/index.vue'
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object,
|
||||
|
|
@ -119,6 +106,10 @@ const inputValue = ref('')
|
|||
const chartOpenId = ref('')
|
||||
const chatList = ref<chatType[]>([])
|
||||
|
||||
const isDisabledChart = computed(
|
||||
() => !(inputValue.value && props.data?.name && props.data?.model_id)
|
||||
)
|
||||
|
||||
function quickProblemHandel(val: string) {
|
||||
inputValue.value = val
|
||||
}
|
||||
|
|
@ -127,8 +118,9 @@ function sendChatHandle(event: any) {
|
|||
if (!event.ctrlKey) {
|
||||
// 如果没有按下组合键ctrl,则会阻止默认事件
|
||||
event.preventDefault()
|
||||
|
||||
chatMessage()
|
||||
if (!isDisabledChart.value) {
|
||||
chatMessage()
|
||||
}
|
||||
} else {
|
||||
// 如果同时按下ctrl+回车键,则会换行
|
||||
inputValue.value += '\n'
|
||||
|
|
@ -162,7 +154,6 @@ function chatMessage() {
|
|||
getChartOpenId()
|
||||
} else {
|
||||
const problem_text = inputValue.value
|
||||
inputValue.value = ''
|
||||
applicationApi.postChatMessage(chartOpenId.value, problem_text).then(async (response) => {
|
||||
const id = randomId()
|
||||
chatList.value.push({
|
||||
|
|
@ -171,6 +162,7 @@ function chatMessage() {
|
|||
answer_text: '',
|
||||
buffer: []
|
||||
})
|
||||
inputValue.value = ''
|
||||
const row = chatList.value.find((item) => item.id === id)
|
||||
if (row) {
|
||||
const chatMange = new ChatManage(row, 50, loading)
|
||||
|
|
|
|||
|
|
@ -38,6 +38,9 @@ import type { FormInstance } from 'element-plus'
|
|||
import triggerApi from '@/api/provider'
|
||||
import type Result from '@/request/Result'
|
||||
import _ from 'lodash'
|
||||
|
||||
defineOptions({ name: 'dynamicsForm' })
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
// 页面渲染数据
|
||||
|
|
|
|||
|
|
@ -12,7 +12,8 @@ import AppTable from './app-table/index.vue'
|
|||
import ReadWrite from './read-write/index.vue'
|
||||
import TagEllipsis from './tag-ellipsis/index.vue'
|
||||
import CommonList from './common-list/index.vue'
|
||||
import dynamicsForm from './dynamics-form'
|
||||
import dynamicsForm from './dynamics-form/index.vue'
|
||||
import MarkdownRenderer from './markdown-renderer/index.vue'
|
||||
export default {
|
||||
install(app: App) {
|
||||
app.component(AppIcon.name, AppIcon)
|
||||
|
|
@ -28,6 +29,7 @@ export default {
|
|||
app.component(ReadWrite.name, ReadWrite)
|
||||
app.component(TagEllipsis.name, TagEllipsis)
|
||||
app.component(CommonList.name, CommonList)
|
||||
app.use(dynamicsForm)
|
||||
app.component(dynamicsForm.name, dynamicsForm)
|
||||
app.component(MarkdownRenderer.name, MarkdownRenderer)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,9 @@ import MarkdownItTasklists from 'markdown-it-task-lists'
|
|||
import MarkdownItSub from 'markdown-it-sub'
|
||||
import MarkdownItSup from 'markdown-it-sup'
|
||||
import MarkdownItTOC from 'markdown-it-toc-done-right'
|
||||
|
||||
defineOptions({ name: 'MarkdownRenderer' })
|
||||
|
||||
const markdownIt = MarkdownIt({
|
||||
html: true, // 允许HTML语法
|
||||
typographer: true, // 启用Typographer插件,可以更好地处理中文字符和标点符号
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ import App from './App.vue'
|
|||
import router from '@/router'
|
||||
import Components from '@/components'
|
||||
|
||||
import 'highlight.js/styles/default.css'
|
||||
const app = createApp(App)
|
||||
app.use(store)
|
||||
app.use(directives)
|
||||
|
|
|
|||
|
|
@ -21,6 +21,12 @@ export const routes: Array<RouteRecordRaw> = [
|
|||
]
|
||||
},
|
||||
|
||||
{
|
||||
path: '/chat/:accessToken',
|
||||
name: 'Chat',
|
||||
component: () => import('@/views/chat/index.vue')
|
||||
},
|
||||
|
||||
{
|
||||
path: '/login',
|
||||
name: 'login',
|
||||
|
|
|
|||
|
|
@ -1,9 +1,12 @@
|
|||
import { defineStore } from 'pinia'
|
||||
import applicationApi from '@/api/application'
|
||||
import { type Ref } from 'vue'
|
||||
|
||||
const useApplicationStore = defineStore({
|
||||
id: 'application',
|
||||
state: () => ({}),
|
||||
state: () => ({
|
||||
location: `${window.location.origin}/ui/chat/`
|
||||
}),
|
||||
actions: {
|
||||
async asyncGetAllApplication() {
|
||||
return new Promise((resolve, reject) => {
|
||||
|
|
@ -16,6 +19,32 @@ const useApplicationStore = defineStore({
|
|||
reject(error)
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
async asyncGetApplicationDetail(id: string, loading?: Ref<boolean>) {
|
||||
return new Promise((resolve, reject) => {
|
||||
applicationApi
|
||||
.getApplicationDetail(id, loading)
|
||||
.then((data) => {
|
||||
resolve(data)
|
||||
})
|
||||
.catch((error) => {
|
||||
reject(error)
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
async asyncGetAccessToken(id: string, loading?: Ref<boolean>) {
|
||||
return new Promise((resolve, reject) => {
|
||||
applicationApi
|
||||
.getAccessToken(id, loading)
|
||||
.then((data) => {
|
||||
resolve(data)
|
||||
})
|
||||
.catch((error) => {
|
||||
reject(error)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -132,6 +132,9 @@ h4 {
|
|||
.ml-16 {
|
||||
margin-left: calc(var(--app-base-px) * 2);
|
||||
}
|
||||
.ml-24 {
|
||||
margin-left: calc(var(--app-base-px) * 3);
|
||||
}
|
||||
.mr-4 {
|
||||
margin-right: calc(var(--app-base-px) - 4px);
|
||||
}
|
||||
|
|
@ -186,6 +189,10 @@ h4 {
|
|||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.border {
|
||||
border: 1px solid var(--el-border-color);
|
||||
}
|
||||
|
||||
.border-l {
|
||||
border-left: 1px solid var(--el-border-color);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
|
||||
@import 'element-plus/dist/index.css';
|
||||
@import './variables.scss';
|
||||
@import './app.scss';
|
||||
@import './element-plus.scss';
|
||||
@import 'nprogress/nprogress.css'
|
||||
|
||||
@import 'nprogress/nprogress.css';
|
||||
@import 'highlight.js/styles/default.css';
|
||||
|
|
|
|||
|
|
@ -7,10 +7,10 @@
|
|||
<AppAvatar class="mr-12" shape="square" :size="32">
|
||||
<img src="@/assets/icon_document.svg" style="width: 58%" alt="" />
|
||||
</AppAvatar>
|
||||
<h4 class="ellipsis-1">应用</h4>
|
||||
<div class="ml-8">
|
||||
<el-tag class="warning-tag">已停用</el-tag>
|
||||
<el-tag class="success-tag">运行中</el-tag>
|
||||
<h4 class="ellipsis-1">{{ detail?.name }}</h4>
|
||||
<div class="ml-8" v-if="detail">
|
||||
<el-tag v-if="detail?.status" class="success-tag">运行中</el-tag>
|
||||
<el-tag v-else class="warning-tag">已停用</el-tag>
|
||||
</div>
|
||||
</div>
|
||||
<div class="active-button" @click.stop>
|
||||
|
|
@ -21,7 +21,7 @@
|
|||
<el-text type="info">公开访问链接</el-text>
|
||||
<div class="mt-4">
|
||||
<span class="vertical-middle lighter">
|
||||
https:/fit2cloud.com/xlab-fit2cloud/smart-doc/16826
|
||||
{{ shareUrl }}
|
||||
</span>
|
||||
|
||||
<el-button type="primary" text>
|
||||
|
|
@ -57,13 +57,59 @@
|
|||
</el-row>
|
||||
<div class="mt-16">
|
||||
<el-button type="primary"> 演示 </el-button>
|
||||
<el-button> 嵌入第三方 </el-button>
|
||||
<el-button @click="openDialog"> 嵌入第三方 </el-button>
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
<EmbedDialog ref="EmbedDialogRef" />
|
||||
</LayoutContainer>
|
||||
</template>
|
||||
<script setup lang="ts"></script>
|
||||
<script setup lang="ts">
|
||||
import { reactive, ref, watch, onMounted } from 'vue'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import applicationApi from '@/api/application'
|
||||
import EmbedDialog from './components/EmbedDialog.vue'
|
||||
import useStore from '@/stores'
|
||||
const { application } = useStore()
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
|
||||
const EmbedDialogRef = ref()
|
||||
const shareUrl = ref('')
|
||||
const detail = ref<any>(null)
|
||||
const apiKey = ref<any>(null)
|
||||
const {
|
||||
params: { id }
|
||||
} = route as any
|
||||
|
||||
const loading = ref(false)
|
||||
|
||||
function openDialog() {
|
||||
EmbedDialogRef.value.open()
|
||||
}
|
||||
function getAccessToken() {
|
||||
application.asyncGetAccessToken(id, loading).then((res) => {
|
||||
shareUrl.value = application.location + res.data
|
||||
})
|
||||
}
|
||||
|
||||
function getApiKey() {
|
||||
applicationApi.getAPIKey(id, loading).then((res) => {
|
||||
apiKey.value = res.data
|
||||
})
|
||||
}
|
||||
|
||||
function getDetail() {
|
||||
application.asyncGetApplicationDetail(id, loading).then((res: any) => {
|
||||
detail.value = res.data
|
||||
})
|
||||
}
|
||||
onMounted(() => {
|
||||
getDetail()
|
||||
getApiKey()
|
||||
getAccessToken()
|
||||
})
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.overview-card {
|
||||
position: relative;
|
||||
|
|
|
|||
|
|
@ -139,9 +139,9 @@
|
|||
</el-scrollbar>
|
||||
</div>
|
||||
<div class="text-right border-t p-16">
|
||||
<el-button @click="router.push({ path: `/application` })"> 取消 </el-button>
|
||||
<el-button v-if="!id" @click="router.push({ path: `/application` })"> 取消 </el-button>
|
||||
<el-button type="primary" @click="submit(applicationFormRef)" :disabled="loading">
|
||||
创建
|
||||
{{ id ? '保存' : '创建' }}
|
||||
</el-button>
|
||||
</div>
|
||||
</el-col>
|
||||
|
|
@ -171,7 +171,7 @@ import type { Provider } from '@/api/type/model'
|
|||
import { realatedObject } from '@/utils/utils'
|
||||
import { MsgSuccess } from '@/utils/message'
|
||||
import useStore from '@/stores'
|
||||
const { model, dataset } = useStore()
|
||||
const { model, dataset, application, user } = useStore()
|
||||
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
|
|
@ -184,7 +184,7 @@ const AddDatasetDialogRef = ref()
|
|||
|
||||
const loading = ref(false)
|
||||
const exampleList = ref(['', ''])
|
||||
const applicationForm = reactive<ApplicationFormType>({
|
||||
const applicationForm = ref<ApplicationFormType>({
|
||||
name: '',
|
||||
desc: '',
|
||||
model_id: '',
|
||||
|
|
@ -209,49 +209,63 @@ const providerOptions = ref<Array<Provider>>([])
|
|||
const datasetList = ref([])
|
||||
|
||||
watch(exampleList.value, () => {
|
||||
applicationForm.example = exampleList.value.filter((v) => v)
|
||||
applicationForm.value.example = exampleList.value.filter((v) => v)
|
||||
})
|
||||
|
||||
const submit = async (formEl: FormInstance | undefined) => {
|
||||
if (!formEl) return
|
||||
await formEl.validate((valid, fields) => {
|
||||
if (valid) {
|
||||
applicationApi
|
||||
.postApplication(applicationForm, loading)
|
||||
.then((res) => {
|
||||
if (id) {
|
||||
applicationApi.putApplication(id, applicationForm.value, loading).then((res) => {
|
||||
MsgSuccess('保存成功')
|
||||
})
|
||||
} else {
|
||||
applicationApi.postApplication(applicationForm.value, loading).then((res) => {
|
||||
MsgSuccess('创建成功')
|
||||
router.push({ path: `/application` })
|
||||
})
|
||||
.catch(() => {
|
||||
loading.value = false
|
||||
})
|
||||
}
|
||||
} else {
|
||||
console.log('error submit!')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function removeDataset(id: String) {
|
||||
applicationForm.dataset_id_list.splice(applicationForm.dataset_id_list.indexOf(id), 1)
|
||||
function removeDataset(id: string) {
|
||||
applicationForm.value.dataset_id_list.splice(applicationForm.value.dataset_id_list.indexOf(id), 1)
|
||||
}
|
||||
function addDataset(val: Array<string>) {
|
||||
applicationForm.dataset_id_list = val
|
||||
applicationForm.value.dataset_id_list = val
|
||||
}
|
||||
function openDatasetDialog() {
|
||||
AddDatasetDialogRef.value.open(applicationForm.dataset_id_list)
|
||||
AddDatasetDialogRef.value.open(applicationForm.value.dataset_id_list)
|
||||
}
|
||||
|
||||
function getDetail() {
|
||||
application.asyncGetApplicationDetail(id, loading).then((res: any) => {
|
||||
applicationForm.value = res.data
|
||||
applicationForm.value.model_id = res.data.model
|
||||
})
|
||||
}
|
||||
|
||||
function getDataset() {
|
||||
loading.value = true
|
||||
dataset
|
||||
.asyncGetAllDateset()
|
||||
.then((res: any) => {
|
||||
if (id) {
|
||||
applicationApi.getApplicationDataset(id, loading).then((res) => {
|
||||
datasetList.value = res.data
|
||||
loading.value = false
|
||||
})
|
||||
.catch(() => {
|
||||
loading.value = false
|
||||
})
|
||||
} else {
|
||||
dataset
|
||||
.asyncGetAllDateset()
|
||||
.then((res: any) => {
|
||||
datasetList.value = res.data?.filter((v) => v.user_id === user.userInfo?.id)
|
||||
loading.value = false
|
||||
})
|
||||
.catch(() => {
|
||||
loading.value = false
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function getModel() {
|
||||
|
|
@ -284,6 +298,9 @@ onMounted(() => {
|
|||
getProvider()
|
||||
getModel()
|
||||
getDataset()
|
||||
if (id) {
|
||||
getDetail()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,97 @@
|
|||
<template>
|
||||
<el-dialog title="嵌入第三方" v-model="dialogVisible" width="900" class="embed-dialog">
|
||||
<el-row :gutter="12">
|
||||
<el-col :span="12">
|
||||
<div class="border">
|
||||
<img src="@/assets/window1.png" alt="" />
|
||||
<div class="code border-t p-16">
|
||||
<div class="flex-between">
|
||||
<span class="bold">复制以下代码进行嵌入</span>
|
||||
<el-button text>
|
||||
<el-icon style="font-size: 13px"><CopyDocument /></el-icon>
|
||||
</el-button>
|
||||
</div>
|
||||
<div class="mt-8">
|
||||
{{ source1 }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<div class="border">
|
||||
<img src="@/assets/window2.png" alt="" />
|
||||
<div class="code border-t p-16">
|
||||
<div class="flex-between">
|
||||
<span class="bold">复制以下代码进行嵌入</span>
|
||||
<el-button text>
|
||||
<el-icon style="font-size: 13px"><CopyDocument /></el-icon>
|
||||
</el-button>
|
||||
</div>
|
||||
<div class="mt-8">
|
||||
{{ source2 }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-dialog>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, watch } from 'vue'
|
||||
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Array<any>,
|
||||
default: () => []
|
||||
}
|
||||
})
|
||||
|
||||
const emit = defineEmits(['addData'])
|
||||
|
||||
const loading = ref(false)
|
||||
const dialogVisible = ref<boolean>(false)
|
||||
const source1 = ref(`<iframe
|
||||
src="https://udify.app/chatbot/ASkyzvhN5Z1h6k7g"
|
||||
style="width: 100%; height: 100%;"
|
||||
frameborder="0"
|
||||
allow="microphone">
|
||||
</iframe>
|
||||
`)
|
||||
|
||||
const source2 = ref(`<script> window.difyChatbotConfig = {
|
||||
token: '85FfbbzTpXzzr40X'
|
||||
}
|
||||
<\/script>
|
||||
<script src="https://udify.app/embed.min.js"
|
||||
id="85FfbbzTpXzzr40X"
|
||||
defer>
|
||||
<\/script>
|
||||
`)
|
||||
|
||||
watch(dialogVisible, (bool) => {
|
||||
if (!bool) {
|
||||
loading.value = false
|
||||
}
|
||||
})
|
||||
|
||||
const open = (checked: any) => {
|
||||
dialogVisible.value = true
|
||||
}
|
||||
const submitHandle = () => {
|
||||
dialogVisible.value = false
|
||||
}
|
||||
|
||||
defineExpose({ open })
|
||||
</script>
|
||||
<style lang="scss" scope>
|
||||
.embed-dialog {
|
||||
.code {
|
||||
color: var(--app-text-color) !important;
|
||||
background: var(--app-layout-bg-color);
|
||||
font-weight: 400;
|
||||
font-size: 13px;
|
||||
white-space: pre;
|
||||
height: 180px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -71,7 +71,7 @@
|
|||
<span>运行中</span>
|
||||
<!-- <el-switch v-model="item.status" @change="changeState($event, item)" /> -->
|
||||
</div>
|
||||
<el-dropdown-item divided>删除</el-dropdown-item>
|
||||
<el-dropdown-item divided @click="deleteApplication(item)">删除</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
|
|
@ -88,9 +88,8 @@
|
|||
import { ref, onMounted, reactive } from 'vue'
|
||||
import applicationApi from '@/api/application'
|
||||
import type { pageRequest } from '@/api/type/common'
|
||||
// import { MsgSuccess, MsgConfirm } from '@/utils/message'
|
||||
import { MsgSuccess, MsgConfirm } from '@/utils/message'
|
||||
import { useRouter } from 'vue-router'
|
||||
// import { numberFormat } from '@/utils/utils'
|
||||
const router = useRouter()
|
||||
|
||||
const loading = ref(false)
|
||||
|
|
@ -102,7 +101,6 @@ const pageConfig = reactive<pageRequest>({
|
|||
})
|
||||
|
||||
const applicationList = ref<any[]>([])
|
||||
const state = ref(false)
|
||||
|
||||
function loadDataset() {}
|
||||
|
||||
|
|
@ -111,29 +109,29 @@ function search() {
|
|||
getList()
|
||||
}
|
||||
|
||||
// function deleteDateset(row: any) {
|
||||
// MsgConfirm(
|
||||
// `是否删除数据集:${row.name} ?`,
|
||||
// `此数据集关联 ${row.char_length} 个应用,删除后无法恢复,请谨慎操作。`,
|
||||
// {
|
||||
// confirmButtonText: '删除',
|
||||
// confirmButtonClass: 'danger'
|
||||
// }
|
||||
// )
|
||||
// .then(() => {
|
||||
// loading.value = true
|
||||
// datasetApi
|
||||
// .delDateset(row.id)
|
||||
// .then(() => {
|
||||
// MsgSuccess('删除成功')
|
||||
// getList()
|
||||
// })
|
||||
// .catch(() => {
|
||||
// loading.value = false
|
||||
// })
|
||||
// })
|
||||
// .catch(() => {})
|
||||
// }
|
||||
function deleteApplication(row: any) {
|
||||
MsgConfirm(
|
||||
`是否删除应用:${row.name} ?`,
|
||||
`删除后该应用将不再提供服务,请谨慎操作。`,
|
||||
{
|
||||
confirmButtonText: '删除',
|
||||
confirmButtonClass: 'danger'
|
||||
}
|
||||
)
|
||||
.then(() => {
|
||||
loading.value = true
|
||||
applicationApi
|
||||
.delApplication(row.id)
|
||||
.then(() => {
|
||||
MsgSuccess('删除成功')
|
||||
getList()
|
||||
})
|
||||
.catch(() => {
|
||||
loading.value = false
|
||||
})
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
|
||||
// function changeState(bool: Boolean, row: any) {
|
||||
// const obj = {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,36 @@
|
|||
<template>
|
||||
<div class="chat">
|
||||
<div class="chat__header">
|
||||
<div class="chat-width"><h2 class="ml-24">111</h2></div>
|
||||
</div>
|
||||
<div class="chat__main chat-width"><AiDialog></AiDialog></div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import AiDialog from '@/components/ai-dialog/index.vue'
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.chat {
|
||||
background-color: var(--app-layout-bg-color);
|
||||
&__header {
|
||||
background: var(--app-header-bg-color);
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
left: 0;
|
||||
top: 0;
|
||||
z-index: 100;
|
||||
height: var(--app-header-height);
|
||||
line-height: var(--app-header-height);
|
||||
box-sizing: border-box;
|
||||
padding: var(--app-header-padding);
|
||||
}
|
||||
&__main {
|
||||
padding-top: calc(var(--app-header-height) + 24px);
|
||||
height: calc(100vh - var(--app-header-height) - 24px);
|
||||
}
|
||||
.chat-width {
|
||||
width: 840px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Loading…
Reference in New Issue