merge
This commit is contained in:
commit
9af53c8821
@ -32,6 +32,7 @@
|
|||||||
"pinia": "^2.1.6",
|
"pinia": "^2.1.6",
|
||||||
"pinyin-pro": "^3.18.2",
|
"pinyin-pro": "^3.18.2",
|
||||||
"vue": "^3.3.4",
|
"vue": "^3.3.4",
|
||||||
|
"vue-clipboard3": "^2.0.0",
|
||||||
"vue-router": "^4.2.4"
|
"vue-router": "^4.2.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
@ -29,32 +29,6 @@ const getApplication: (param: pageRequest) => Promise<Result<any>> = (param) =>
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 获得临时回话Id
|
|
||||||
* @param 参数
|
|
||||||
* {
|
|
||||||
"model_id": "string",
|
|
||||||
"multiple_rounds_dialogue": true,
|
|
||||||
"dataset_id_list": [
|
|
||||||
"string"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
const postChatOpen: (data: ApplicationFormType) => Promise<Result<any>> = (data) => {
|
|
||||||
return post(`${prefix}/chat/open`, data)
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* 对话
|
|
||||||
* @param 参数
|
|
||||||
* chat_id: string
|
|
||||||
* {
|
|
||||||
"message": "string",
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
const postChatMessage: (chat_id: string, message: string) => Promise<any> = (chat_id, message) => {
|
|
||||||
return postStream(`/api/${prefix}/chat_message/${chat_id}`, { message })
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建应用
|
* 创建应用
|
||||||
* @param 参数
|
* @param 参数
|
||||||
@ -156,16 +130,85 @@ const getAccessToken: (applicaiton_id: string, loading?: Ref<boolean>) => Promis
|
|||||||
return get(`${prefix}/${applicaiton_id}/access_token`, undefined, loading)
|
return get(`${prefix}/${applicaiton_id}/access_token`, undefined, loading)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用认证
|
||||||
|
* @param 参数
|
||||||
|
{
|
||||||
|
"access_token": "string"
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
const postAppAuthentication: (access_token: string, loading?: Ref<boolean>) => Promise<any> = (
|
||||||
|
access_token,
|
||||||
|
loading
|
||||||
|
) => {
|
||||||
|
return post(`${prefix}/authentication`, { access_token }, undefined, loading)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 对话获取应用相关信息
|
||||||
|
* @param 参数
|
||||||
|
{
|
||||||
|
"access_token": "string"
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
const getProfile: (loading?: Ref<boolean>) => Promise<any> = (loading) => {
|
||||||
|
return get(`${prefix}/profile`, undefined, loading)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得临时回话Id
|
||||||
|
* @param 参数
|
||||||
|
* {
|
||||||
|
"model_id": "string",
|
||||||
|
"multiple_rounds_dialogue": true,
|
||||||
|
"dataset_id_list": [
|
||||||
|
"string"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
const postChatOpen: (data: ApplicationFormType) => Promise<Result<any>> = (data) => {
|
||||||
|
return post(`${prefix}/chat/open`, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 正式回话Id
|
||||||
|
* @param 参数
|
||||||
|
* {
|
||||||
|
"model_id": "string",
|
||||||
|
"multiple_rounds_dialogue": true,
|
||||||
|
"dataset_id_list": [
|
||||||
|
"string"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
const getChatOpen: (applicaiton_id: String) => Promise<Result<any>> = (applicaiton_id) => {
|
||||||
|
return get(`${prefix}/${applicaiton_id}/chat/open`)
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 对话
|
||||||
|
* @param 参数
|
||||||
|
* chat_id: string
|
||||||
|
* {
|
||||||
|
"message": "string",
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
const postChatMessage: (chat_id: string, message: string) => Promise<any> = (chat_id, message) => {
|
||||||
|
return postStream(`/api/${prefix}/chat_message/${chat_id}`, { message })
|
||||||
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
getAllAppilcation,
|
getAllAppilcation,
|
||||||
getApplication,
|
getApplication,
|
||||||
postApplication,
|
postApplication,
|
||||||
putApplication,
|
putApplication,
|
||||||
postChatOpen,
|
postChatOpen,
|
||||||
|
getChatOpen,
|
||||||
postChatMessage,
|
postChatMessage,
|
||||||
delApplication,
|
delApplication,
|
||||||
getApplicationDetail,
|
getApplicationDetail,
|
||||||
getApplicationDataset,
|
getApplicationDataset,
|
||||||
getAPIKey,
|
getAPIKey,
|
||||||
getAccessToken
|
getAccessToken,
|
||||||
|
postAppAuthentication,
|
||||||
|
getProfile
|
||||||
}
|
}
|
||||||
|
|||||||
51
ui/src/components/ai-dialog/OperationButton.vue
Normal file
51
ui/src/components/ai-dialog/OperationButton.vue
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<el-tooltip effect="dark" content="重新生成" placement="top">
|
||||||
|
<el-button text @click.stop>
|
||||||
|
<AppIcon iconName="VideoPlay"></AppIcon>
|
||||||
|
</el-button>
|
||||||
|
</el-tooltip>
|
||||||
|
<el-divider direction="vertical" />
|
||||||
|
<el-tooltip effect="dark" content="复制" placement="top">
|
||||||
|
<el-button text @click="copyClick(item?.answer_text)">
|
||||||
|
<AppIcon iconName="app-copy"></AppIcon>
|
||||||
|
</el-button>
|
||||||
|
</el-tooltip>
|
||||||
|
<el-divider direction="vertical" />
|
||||||
|
<el-tooltip effect="dark" content="赞同" placement="top">
|
||||||
|
<el-button text>
|
||||||
|
<AppIcon iconName="app-like"></AppIcon>
|
||||||
|
</el-button>
|
||||||
|
</el-tooltip>
|
||||||
|
<el-tooltip effect="dark" content="取消赞同" placement="top">
|
||||||
|
<el-button text>
|
||||||
|
<AppIcon iconName="app-like-color"></AppIcon>
|
||||||
|
</el-button>
|
||||||
|
</el-tooltip>
|
||||||
|
<el-divider direction="vertical" />
|
||||||
|
<el-tooltip effect="dark" content="反对" placement="top">
|
||||||
|
<el-button text>
|
||||||
|
<AppIcon iconName="app-oppose"></AppIcon>
|
||||||
|
</el-button>
|
||||||
|
</el-tooltip>
|
||||||
|
<el-tooltip effect="dark" content="取消反对" placement="top">
|
||||||
|
<el-button text>
|
||||||
|
<AppIcon iconName="app-oppose-color"></AppIcon>
|
||||||
|
</el-button>
|
||||||
|
</el-tooltip>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { copyClick } from '@/utils/clipboard'
|
||||||
|
|
||||||
|
defineProps({
|
||||||
|
data: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const emit = defineEmits(['update:data'])
|
||||||
|
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped></style>
|
||||||
@ -64,23 +64,25 @@
|
|||||||
:inner_suffix="false"
|
:inner_suffix="false"
|
||||||
></MarkdownRenderer>
|
></MarkdownRenderer>
|
||||||
</el-card>
|
</el-card>
|
||||||
|
<div class="flex-between mt-8">
|
||||||
|
<div>
|
||||||
<el-button
|
<el-button
|
||||||
type="primary"
|
type="primary"
|
||||||
v-if="item.is_stop && !item.write_ed"
|
v-if="item.is_stop && !item.write_ed"
|
||||||
@click="startChat(item)"
|
@click="startChat(item)"
|
||||||
link
|
link
|
||||||
class="mt-8"
|
|
||||||
>继续</el-button
|
>继续</el-button
|
||||||
>
|
>
|
||||||
<el-button
|
<el-button type="primary" v-else-if="!item.write_ed" @click="stopChat(item)" link
|
||||||
type="primary"
|
|
||||||
v-else-if="!item.write_ed"
|
|
||||||
@click="stopChat(item)"
|
|
||||||
link
|
|
||||||
class="mt-8"
|
|
||||||
>停止回答</el-button
|
>停止回答</el-button
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- <div v-if="item.write_ed && props.appId">
|
||||||
|
<OperationButton :data="item" />
|
||||||
|
</div> -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
@ -107,6 +109,7 @@
|
|||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, nextTick, onUpdated, computed } from 'vue'
|
import { ref, nextTick, onUpdated, computed } from 'vue'
|
||||||
|
import OperationButton from './OperationButton.vue'
|
||||||
import applicationApi from '@/api/application'
|
import applicationApi from '@/api/application'
|
||||||
import { ChatManagement, type chatType } from '@/api/type/application'
|
import { ChatManagement, type chatType } from '@/api/type/application'
|
||||||
import { randomId } from '@/utils/utils'
|
import { randomId } from '@/utils/utils'
|
||||||
@ -114,7 +117,8 @@ const props = defineProps({
|
|||||||
data: {
|
data: {
|
||||||
type: Object,
|
type: Object,
|
||||||
default: () => {}
|
default: () => {}
|
||||||
}
|
},
|
||||||
|
appId: String
|
||||||
})
|
})
|
||||||
|
|
||||||
const scrollDiv = ref()
|
const scrollDiv = ref()
|
||||||
@ -125,7 +129,7 @@ const chartOpenId = ref('')
|
|||||||
const chatList = ref<chatType[]>([])
|
const chatList = ref<chatType[]>([])
|
||||||
|
|
||||||
const isDisabledChart = computed(
|
const isDisabledChart = computed(
|
||||||
() => !(inputValue.value && props.data?.name && props.data?.model_id)
|
() => !(inputValue.value && (props.appId || (props.data?.name && props.data?.model_id)))
|
||||||
)
|
)
|
||||||
|
|
||||||
function quickProblemHandel(val: string) {
|
function quickProblemHandel(val: string) {
|
||||||
@ -160,6 +164,17 @@ function getChartOpenId() {
|
|||||||
dataset_id_list: props.data.dataset_id_list,
|
dataset_id_list: props.data.dataset_id_list,
|
||||||
multiple_rounds_dialogue: props.data.multiple_rounds_dialogue
|
multiple_rounds_dialogue: props.data.multiple_rounds_dialogue
|
||||||
}
|
}
|
||||||
|
if (props.appId) {
|
||||||
|
applicationApi
|
||||||
|
.getChatOpen(props.appId)
|
||||||
|
.then((res) => {
|
||||||
|
chartOpenId.value = res.data
|
||||||
|
chatMessage()
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
loading.value = false
|
||||||
|
})
|
||||||
|
} else {
|
||||||
applicationApi
|
applicationApi
|
||||||
.postChatOpen(obj)
|
.postChatOpen(obj)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
@ -170,6 +185,7 @@ function getChartOpenId() {
|
|||||||
loading.value = false
|
loading.value = false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
}
|
||||||
function chatMessage() {
|
function chatMessage() {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
if (!chartOpenId.value) {
|
if (!chartOpenId.value) {
|
||||||
@ -188,10 +204,12 @@ function chatMessage() {
|
|||||||
applicationApi.postChatMessage(chartOpenId.value, problem_text).then(async (response) => {
|
applicationApi.postChatMessage(chartOpenId.value, problem_text).then(async (response) => {
|
||||||
inputValue.value = ''
|
inputValue.value = ''
|
||||||
const row = chatList.value.find((item) => item.id === id)
|
const row = chatList.value.find((item) => item.id === id)
|
||||||
|
|
||||||
if (row) {
|
if (row) {
|
||||||
ChatManagement.addChatRecord(row, 50, loading)
|
ChatManagement.addChatRecord(row, 50, loading)
|
||||||
ChatManagement.write(id)
|
ChatManagement.write(id)
|
||||||
const reader = response.body.getReader()
|
const reader = response.body.getReader()
|
||||||
|
/*eslint no-constant-condition: ["error", { "checkLoops": false }]*/
|
||||||
while (true) {
|
while (true) {
|
||||||
const { done, value } = await reader.read()
|
const { done, value } = await reader.read()
|
||||||
if (done) {
|
if (done) {
|
||||||
@ -203,11 +221,14 @@ function chatMessage() {
|
|||||||
const str = decoder.decode(value, { stream: true })
|
const str = decoder.decode(value, { stream: true })
|
||||||
if (str && str.startsWith('data:')) {
|
if (str && str.startsWith('data:')) {
|
||||||
const content = JSON?.parse(str.replace('data:', ''))?.content
|
const content = JSON?.parse(str.replace('data:', ''))?.content
|
||||||
|
|
||||||
if (content) {
|
if (content) {
|
||||||
ChatManagement.append(id, content)
|
ChatManagement.append(id, content)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e) {}
|
} catch (e) {
|
||||||
|
// console
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@ -8,7 +8,7 @@
|
|||||||
</el-avatar>
|
</el-avatar>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { pinyin } from 'pinyin-pro';
|
import { pinyin } from 'pinyin-pro'
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
defineOptions({ name: 'AppAvatar' })
|
defineOptions({ name: 'AppAvatar' })
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
@ -26,37 +26,31 @@ const firstUserName = computed(() => {
|
|||||||
return props.name?.substring(0, 1)
|
return props.name?.substring(0, 1)
|
||||||
})
|
})
|
||||||
|
|
||||||
function getAvatarColour(name: string) {
|
const getAvatarColour = (name: string) => {
|
||||||
const charIndex = pinyin.getFullChars(name).charAt(0).toUpperCase().charCodeAt(0) - 65
|
|
||||||
const colours = [
|
const colours = [
|
||||||
'#ACA9E5',
|
'#3370FF',
|
||||||
'#BCC934',
|
'#4954E6',
|
||||||
'#B3CFE8',
|
'#F54A45',
|
||||||
'#DCDEB5',
|
'#00B69D',
|
||||||
'#D65A4A',
|
'#2CA91F',
|
||||||
'#E0C78B',
|
'#98B600',
|
||||||
'#E59191',
|
'#F80F80',
|
||||||
'#E99334',
|
'#D136D1',
|
||||||
'#FF6632',
|
'#F01D94',
|
||||||
'#F4B7EF',
|
'#7F3BF5',
|
||||||
'#F7D407',
|
'#8F959E'
|
||||||
'#F8BB98',
|
|
||||||
'#2BCBB1',
|
|
||||||
'#3594F1',
|
|
||||||
'#486660',
|
|
||||||
'#4B689F',
|
|
||||||
'#5976F6',
|
|
||||||
'#72B1B2',
|
|
||||||
'#778293',
|
|
||||||
'#7D6624',
|
|
||||||
'#82CBB5',
|
|
||||||
'#837F6A',
|
|
||||||
'#87B087',
|
|
||||||
'#9AC0C4',
|
|
||||||
'#958E55',
|
|
||||||
'#99E4F2'
|
|
||||||
]
|
]
|
||||||
|
let charIndex = name ? pinyin(name).charAt(0).toUpperCase().charCodeAt(0) - 65 : 0
|
||||||
|
|
||||||
|
function getColor() {
|
||||||
|
if (!colours[charIndex]) {
|
||||||
|
charIndex -= 10
|
||||||
|
getColor()
|
||||||
|
}
|
||||||
return colours[charIndex]
|
return colours[charIndex]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return getColor()
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped></style>
|
<style lang="scss" scoped></style>
|
||||||
|
|||||||
@ -3,10 +3,11 @@
|
|||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<slot name="header">
|
<slot name="header">
|
||||||
<div class="title flex align-center">
|
<div class="title flex align-center">
|
||||||
<AppAvatar v-if="!slots.icon && showIcon" class="mr-12" shape="square" :size="32">
|
<slot name="icon">
|
||||||
|
<AppAvatar v-if="showIcon" class="mr-12" shape="square" :size="32">
|
||||||
<img src="@/assets/icon_document.svg" style="width: 58%" alt="" />
|
<img src="@/assets/icon_document.svg" style="width: 58%" alt="" />
|
||||||
</AppAvatar>
|
</AppAvatar>
|
||||||
<slot v-else name="icon"> </slot>
|
</slot>
|
||||||
<h4 class="ellipsis-1" style="width: 100%">{{ title }}</h4>
|
<h4 class="ellipsis-1" style="width: 100%">{{ title }}</h4>
|
||||||
</div>
|
</div>
|
||||||
</slot>
|
</slot>
|
||||||
|
|||||||
@ -2,18 +2,10 @@
|
|||||||
<div class="common-list">
|
<div class="common-list">
|
||||||
<el-scrollbar>
|
<el-scrollbar>
|
||||||
<ul v-if="data.length > 0">
|
<ul v-if="data.length > 0">
|
||||||
<li
|
|
||||||
v-if="slots.prefix"
|
|
||||||
@click="clickHandle()"
|
|
||||||
:class="modelValue === undefined || modelValue === null ? 'active' : ''"
|
|
||||||
class="cursor"
|
|
||||||
>
|
|
||||||
<slot name="prefix"> </slot>
|
|
||||||
</li>
|
|
||||||
<template v-for="(item, index) in data" :key="index">
|
<template v-for="(item, index) in data" :key="index">
|
||||||
<li
|
<li
|
||||||
@click.prevent="clickHandle(item)"
|
@click.prevent="clickHandle(item, index)"
|
||||||
:class="modelValue === item ? 'active' : ''"
|
:class="current === index ? 'active' : ''"
|
||||||
class="cursor"
|
class="cursor"
|
||||||
>
|
>
|
||||||
<slot :row="item" :index="index"> </slot>
|
<slot :row="item" :index="index"> </slot>
|
||||||
@ -32,8 +24,6 @@ defineOptions({ name: 'CommonList' })
|
|||||||
|
|
||||||
withDefaults(
|
withDefaults(
|
||||||
defineProps<{
|
defineProps<{
|
||||||
modelValue?: any
|
|
||||||
|
|
||||||
data: Array<any>
|
data: Array<any>
|
||||||
}>(),
|
}>(),
|
||||||
{
|
{
|
||||||
@ -41,11 +31,13 @@ withDefaults(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
const emit = defineEmits(['click', 'update:modelValue'])
|
const emit = defineEmits(['click'])
|
||||||
|
|
||||||
function clickHandle(row?: any) {
|
const current = ref(0)
|
||||||
|
|
||||||
|
function clickHandle(row: any, index: number) {
|
||||||
|
current.value = index
|
||||||
emit('click', row)
|
emit('click', row)
|
||||||
emit('update:modelValue', row)
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|||||||
@ -308,5 +308,139 @@ export const iconMap: any = {
|
|||||||
)
|
)
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
'app-restore': {
|
||||||
|
iconReader: () => {
|
||||||
|
return h('i', [
|
||||||
|
h(
|
||||||
|
'svg',
|
||||||
|
{
|
||||||
|
style: { height: '100%', width: '100%' },
|
||||||
|
viewBox: '0 0 16 16',
|
||||||
|
version: '1.1',
|
||||||
|
xmlns: 'http://www.w3.org/2000/svg'
|
||||||
|
},
|
||||||
|
[
|
||||||
|
h('path', {
|
||||||
|
d: 'M3.33333 5.3335V13.3335H10V5.3335H3.33333ZM11.3333 4.66683V14.0742C11.3333 14.4015 11.0548 14.6668 10.7111 14.6668H2.62222C2.27858 14.6668 2 14.4015 2 14.0742V4.59276C2 4.26548 2.27858 4.00016 2.62222 4.00016H10.6667C11.0349 4.00016 11.3333 4.29864 11.3333 4.66683ZM13.8047 1.52876C13.9254 1.6494 14 1.81607 14 2.00016V10.3335C14 10.5176 13.8508 10.6668 13.6667 10.6668H13C12.8159 10.6668 12.6667 10.5176 12.6667 10.3335V2.66683H6.33333C6.14924 2.66683 6 2.51759 6 2.3335V1.66683C6 1.48273 6.14924 1.3335 6.33333 1.3335H13.3333C13.5174 1.3335 13.6841 1.40812 13.8047 1.52876Z',
|
||||||
|
fill: 'currentColor'
|
||||||
|
})
|
||||||
|
]
|
||||||
|
)
|
||||||
|
])
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
'app-copy': {
|
||||||
|
iconReader: () => {
|
||||||
|
return h('i', [
|
||||||
|
h(
|
||||||
|
'svg',
|
||||||
|
{
|
||||||
|
style: { height: '100%', width: '100%' },
|
||||||
|
viewBox: '0 0 16 16',
|
||||||
|
version: '1.1',
|
||||||
|
xmlns: 'http://www.w3.org/2000/svg'
|
||||||
|
},
|
||||||
|
[
|
||||||
|
h('path', {
|
||||||
|
d: 'M3.33333 5.3335V13.3335H10V5.3335H3.33333ZM11.3333 4.66683V14.0742C11.3333 14.4015 11.0548 14.6668 10.7111 14.6668H2.62222C2.27858 14.6668 2 14.4015 2 14.0742V4.59276C2 4.26548 2.27858 4.00016 2.62222 4.00016H10.6667C11.0349 4.00016 11.3333 4.29864 11.3333 4.66683ZM13.8047 1.52876C13.9254 1.6494 14 1.81607 14 2.00016V10.3335C14 10.5176 13.8508 10.6668 13.6667 10.6668H13C12.8159 10.6668 12.6667 10.5176 12.6667 10.3335V2.66683H6.33333C6.14924 2.66683 6 2.51759 6 2.3335V1.66683C6 1.48273 6.14924 1.3335 6.33333 1.3335H13.3333C13.5174 1.3335 13.6841 1.40812 13.8047 1.52876Z',
|
||||||
|
fill: 'currentColor'
|
||||||
|
})
|
||||||
|
]
|
||||||
|
)
|
||||||
|
])
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'app-like': {
|
||||||
|
iconReader: () => {
|
||||||
|
return h('i', [
|
||||||
|
h(
|
||||||
|
'svg',
|
||||||
|
{
|
||||||
|
style: { height: '100%', width: '100%' },
|
||||||
|
viewBox: '0 0 16 16',
|
||||||
|
version: '1.1',
|
||||||
|
xmlns: 'http://www.w3.org/2000/svg'
|
||||||
|
},
|
||||||
|
[
|
||||||
|
h('path', {
|
||||||
|
d: 'M2.00518 14.6608H0.666612C0.666097 14.6874 0.666707 5.33317 0.666612 5.29087H2.00518C2.00004 5.33317 1.98014 14.6874 2.00518 14.6608ZM9.70096 5.28984H12.5717C14.5687 5.28984 15.0274 7.05264 14.5687 8.37353L12.5717 13.6308C12.4029 14.2423 11.8409 14.6665 11.1995 14.6665H3.33882C3.154 14.6665 3.00418 14.5167 3.00418 14.3319V5.62448C3.00418 5.43966 3.154 5.28984 3.33882 5.28984H4.02656C4.24449 5.28984 4.44877 5.18374 4.5741 5.00545L7.35254 1.05296C7.5406 0.753754 8.04824 0.52438 8.5893 0.770777C9.40089 1.14037 10.3724 1.94718 10.3724 3.28394C10.3724 3.78809 10.1486 4.45673 9.70096 5.28984ZM12.5717 6.62841H7.46215L8.52183 4.65626C8.87422 4.00045 9.03388 3.52351 9.03388 3.28394C9.03388 2.89556 8.9524 2.45627 8.25544 2.09612L5.26934 6.34402C5.14401 6.5223 4.93973 6.62841 4.72181 6.62841H4.34275V13.3279H11.1995C11.2411 13.3279 11.2734 13.3035 11.2813 13.2747L11.298 13.2142L13.3098 7.91815C13.5743 7.13902 13.3105 6.62841 12.5717 6.62841Z',
|
||||||
|
fill: 'currentColor'
|
||||||
|
})
|
||||||
|
]
|
||||||
|
)
|
||||||
|
])
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'app-like-color': {
|
||||||
|
iconReader: () => {
|
||||||
|
return h('i', [
|
||||||
|
h(
|
||||||
|
'svg',
|
||||||
|
{
|
||||||
|
style: { height: '100%', width: '100%' },
|
||||||
|
viewBox: '0 0 16 16',
|
||||||
|
version: '1.1',
|
||||||
|
xmlns: 'http://www.w3.org/2000/svg'
|
||||||
|
},
|
||||||
|
[
|
||||||
|
h('path', {
|
||||||
|
d: 'M2.00497 14.6608H2.00518C2.00511 14.6609 2.00504 14.6609 2.00497 14.6608H0.666612C0.666097 14.6874 0.666707 5.33317 0.666612 5.29087H2.00518C2.00006 5.33305 1.98026 14.6344 2.00497 14.6608Z',
|
||||||
|
fill: '#FFC60A'
|
||||||
|
}),
|
||||||
|
h('path', {
|
||||||
|
d: 'M12.5717 5.28984H9.70096C10.1486 4.45673 10.3724 3.78809 10.3724 3.28394C10.3724 1.94718 9.40089 1.14037 8.5893 0.770777C8.04824 0.52438 7.5406 0.753754 7.35254 1.05296L4.5741 5.00545C4.44877 5.18374 4.24449 5.28984 4.02656 5.28984H3.33882C3.154 5.28984 3.00418 5.43966 3.00418 5.62448V14.3319C3.00418 14.5167 3.154 14.6665 3.33882 14.6665H11.1995C11.8409 14.6665 12.4029 14.2423 12.5717 13.6308L14.5687 8.37353C15.0274 7.05264 14.5687 5.28984 12.5717 5.28984Z',
|
||||||
|
fill: '#FFC60A'
|
||||||
|
})
|
||||||
|
]
|
||||||
|
)
|
||||||
|
])
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'app-oppose': {
|
||||||
|
iconReader: () => {
|
||||||
|
return h('i', [
|
||||||
|
h(
|
||||||
|
'svg',
|
||||||
|
{
|
||||||
|
style: { height: '100%', width: '100%' },
|
||||||
|
viewBox: '0 0 16 16',
|
||||||
|
version: '1.1',
|
||||||
|
xmlns: 'http://www.w3.org/2000/svg'
|
||||||
|
},
|
||||||
|
[
|
||||||
|
h('path', {
|
||||||
|
d: 'M2.00518 1.28008H0.666616C0.666616 1.33341 0.666504 10.6667 0.666616 10.65H2.00518C1.99984 10.6667 1.99984 1.33341 2.00518 1.28008ZM9.70097 10.6511H12.5717C14.5687 10.6511 15.0274 8.88828 14.5687 7.56739L12.5717 2.3101C12.4029 1.69862 11.8409 1.27441 11.1996 1.27441H3.33883C3.15401 1.27441 3.00418 1.42424 3.00418 1.60906V10.3164C3.00418 10.5013 3.15401 10.6511 3.33883 10.6511H4.02656C4.24449 10.6511 4.44877 10.7572 4.5741 10.9355L7.35254 14.888C7.5406 15.1872 8.04825 15.4165 8.58931 15.1701C9.40089 14.8005 10.3724 13.9937 10.3724 12.657C10.3724 12.1528 10.1486 11.4842 9.70097 10.6511ZM12.5717 9.31251H7.46216L8.52184 11.2847C8.87422 11.9405 9.03388 12.4174 9.03388 12.657C9.03388 13.0454 8.95241 13.4846 8.25545 13.8448L5.26935 9.5969C5.14402 9.41861 4.93974 9.31251 4.72181 9.31251H4.34275V2.61298H11.1996C11.2411 2.61298 11.2734 2.63737 11.2813 2.6662L11.298 2.72673L13.3098 8.02277C13.5743 8.8019 13.3105 9.31251 12.5717 9.31251Z',
|
||||||
|
fill: 'currentColor'
|
||||||
|
}),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
])
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'app-oppose-color': {
|
||||||
|
iconReader: () => {
|
||||||
|
return h('i', [
|
||||||
|
h(
|
||||||
|
'svg',
|
||||||
|
{
|
||||||
|
style: { height: '100%', width: '100%' },
|
||||||
|
viewBox: '0 0 16 16',
|
||||||
|
version: '1.1',
|
||||||
|
xmlns: 'http://www.w3.org/2000/svg'
|
||||||
|
},
|
||||||
|
[
|
||||||
|
h('path', {
|
||||||
|
d: 'M9.70106 10.7102H12.5718C14.5688 10.7102 15.0275 8.94736 14.5688 7.62647L12.5718 2.36918C12.403 1.7577 11.841 1.3335 11.1996 1.3335H3.33891C3.1541 1.3335 3.00427 1.48332 3.00427 1.66814V10.3755C3.00427 10.5603 3.1541 10.7102 3.33891 10.7102H4.02665C4.24458 10.7102 4.44886 10.8163 4.57419 10.9945L7.35263 14.947C7.54069 15.2462 8.04834 15.4756 8.58939 15.2292C9.40098 14.8596 10.3725 14.0528 10.3725 12.7161C10.3725 12.2119 10.1487 11.5433 9.70106 10.7102Z',
|
||||||
|
fill: '#F54A45'
|
||||||
|
}),
|
||||||
|
h('path', {
|
||||||
|
d: 'M2.00004 1.3335H0.661473C0.661473 1.3335 0.660982 10.7764 0.661473 10.7035H2.00001C1.99469 10.6868 1.9947 1.38674 2.00004 1.3335Z',
|
||||||
|
fill: '#F54A45'
|
||||||
|
})
|
||||||
|
]
|
||||||
|
)
|
||||||
|
])
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,10 +11,19 @@
|
|||||||
<template v-for="(item, index) in list" :key="index">
|
<template v-for="(item, index) in list" :key="index">
|
||||||
<div :class="item.id === id ? 'dropdown-active' : ''">
|
<div :class="item.id === id ? 'dropdown-active' : ''">
|
||||||
<el-dropdown-item :command="item.id">
|
<el-dropdown-item :command="item.id">
|
||||||
<div class="flex">
|
<div class="flex align-center">
|
||||||
<AppAvatar class="mr-12" shape="square" :size="24">
|
<AppAvatar
|
||||||
|
v-if="isApplication"
|
||||||
|
:name="item.name"
|
||||||
|
pinyinColor
|
||||||
|
class="mr-12"
|
||||||
|
shape="square"
|
||||||
|
:size="24"
|
||||||
|
/>
|
||||||
|
<AppAvatar v-else-if="isDataset" class="mr-12" shape="square" :size="24">
|
||||||
<img src="@/assets/icon_document.svg" style="width: 58%" alt="" />
|
<img src="@/assets/icon_document.svg" style="width: 58%" alt="" />
|
||||||
</AppAvatar>
|
</AppAvatar>
|
||||||
|
|
||||||
<span class="ellipsis-1"> {{ item?.name }}</span>
|
<span class="ellipsis-1"> {{ item?.name }}</span>
|
||||||
</div>
|
</div>
|
||||||
</el-dropdown-item>
|
</el-dropdown-item>
|
||||||
|
|||||||
@ -2,11 +2,7 @@
|
|||||||
<div v-if="!menu.meta || !menu.meta.hidden" class="sidebar-item">
|
<div v-if="!menu.meta || !menu.meta.hidden" class="sidebar-item">
|
||||||
<el-menu-item ref="subMenu" :index="menu.path" popper-class="sidebar-popper">
|
<el-menu-item ref="subMenu" :index="menu.path" popper-class="sidebar-popper">
|
||||||
<template #title>
|
<template #title>
|
||||||
<AppIcon
|
<AppIcon v-if="menu.meta && menu.meta.icon" :iconName="menuIcon" class="sidebar-icon" />
|
||||||
v-if="menu.meta && menu.meta.icon"
|
|
||||||
:iconName="menu.meta.icon"
|
|
||||||
class="sidebar-icon"
|
|
||||||
/>
|
|
||||||
<span v-if="menu.meta && menu.meta.title">{{ menu.meta.title }}</span>
|
<span v-if="menu.meta && menu.meta.title">{{ menu.meta.title }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-menu-item>
|
</el-menu-item>
|
||||||
@ -14,11 +10,20 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { computed } from 'vue'
|
||||||
import { type RouteRecordRaw } from 'vue-router'
|
import { type RouteRecordRaw } from 'vue-router'
|
||||||
|
|
||||||
defineProps<{
|
const props = defineProps<{
|
||||||
menu: RouteRecordRaw
|
menu: RouteRecordRaw
|
||||||
|
activeMenu: any
|
||||||
}>()
|
}>()
|
||||||
|
const menuIcon = computed(() => {
|
||||||
|
if (props.activeMenu === props.menu.path) {
|
||||||
|
return props.menu.meta?.iconActive || props.menu?.meta?.icon
|
||||||
|
} else {
|
||||||
|
return props.menu?.meta?.icon
|
||||||
|
}
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
|
|||||||
@ -10,6 +10,7 @@
|
|||||||
v-for="(menu, index) in subMenuList"
|
v-for="(menu, index) in subMenuList"
|
||||||
:key="index"
|
:key="index"
|
||||||
:menu="menu"
|
:menu="menu"
|
||||||
|
:activeMenu="activeMenu"
|
||||||
>
|
>
|
||||||
</sidebar-item>
|
</sidebar-item>
|
||||||
</el-menu>
|
</el-menu>
|
||||||
|
|||||||
@ -7,14 +7,13 @@ import {
|
|||||||
type RouteRecordRaw,
|
type RouteRecordRaw,
|
||||||
type RouteRecordName
|
type RouteRecordName
|
||||||
} from 'vue-router'
|
} from 'vue-router'
|
||||||
import useStore from '@/stores';
|
import useStore from '@/stores'
|
||||||
import { routes } from '@/router/routes'
|
import { routes } from '@/router/routes'
|
||||||
const router = createRouter({
|
const router = createRouter({
|
||||||
history: createWebHistory(import.meta.env.BASE_URL),
|
history: createWebHistory(import.meta.env.BASE_URL),
|
||||||
routes: routes
|
routes: routes
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
// 路由前置拦截器
|
// 路由前置拦截器
|
||||||
router.beforeEach(
|
router.beforeEach(
|
||||||
async (to: RouteLocationNormalized, from: RouteLocationNormalized, next: NavigationGuardNext) => {
|
async (to: RouteLocationNormalized, from: RouteLocationNormalized, next: NavigationGuardNext) => {
|
||||||
@ -22,8 +21,8 @@ router.beforeEach(
|
|||||||
next()
|
next()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const { user } = useStore();
|
const { user } = useStore()
|
||||||
const notAuthRouteNameList = ['register', 'login', 'forgot_password', 'reset_password']
|
const notAuthRouteNameList = ['register', 'login', 'forgot_password', 'reset_password', 'Chat']
|
||||||
|
|
||||||
if (!notAuthRouteNameList.includes(to.name ? to.name.toString() : '')) {
|
if (!notAuthRouteNameList.includes(to.name ? to.name.toString() : '')) {
|
||||||
const token = user.getToken()
|
const token = user.getToken()
|
||||||
|
|||||||
@ -28,7 +28,8 @@ const applicationRouter = {
|
|||||||
path: 'overview',
|
path: 'overview',
|
||||||
name: 'AppOverview',
|
name: 'AppOverview',
|
||||||
meta: {
|
meta: {
|
||||||
icon: 'Document',
|
icon: 'app-all-menu',
|
||||||
|
iconActive: 'app-all-menu-active',
|
||||||
title: '概览',
|
title: '概览',
|
||||||
active: 'overview',
|
active: 'overview',
|
||||||
parentPath: '/application/:id',
|
parentPath: '/application/:id',
|
||||||
|
|||||||
@ -45,6 +45,20 @@ const useApplicationStore = defineStore({
|
|||||||
reject(error)
|
reject(error)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
async asyncAppAuthentication(token: string, loading?: Ref<boolean>) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
applicationApi
|
||||||
|
.postAppAuthentication(token, loading)
|
||||||
|
.then((res) => {
|
||||||
|
localStorage.setItem('accessToken', res.data)
|
||||||
|
resolve(res)
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
reject(error)
|
||||||
|
})
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@ -3,6 +3,7 @@ import type { User } from '@/api/type/user'
|
|||||||
import UserApi from '@/api/user'
|
import UserApi from '@/api/user'
|
||||||
|
|
||||||
export interface userStateTypes {
|
export interface userStateTypes {
|
||||||
|
userType: number // 1 系统操作者 2 对话用户
|
||||||
userInfo: User | null
|
userInfo: User | null
|
||||||
token: any
|
token: any
|
||||||
}
|
}
|
||||||
@ -10,6 +11,7 @@ export interface userStateTypes {
|
|||||||
const useUserStore = defineStore({
|
const useUserStore = defineStore({
|
||||||
id: 'user',
|
id: 'user',
|
||||||
state: (): userStateTypes => ({
|
state: (): userStateTypes => ({
|
||||||
|
userType: 1,
|
||||||
userInfo: null,
|
userInfo: null,
|
||||||
token: ''
|
token: ''
|
||||||
}),
|
}),
|
||||||
@ -18,7 +20,9 @@ const useUserStore = defineStore({
|
|||||||
if (this.token) {
|
if (this.token) {
|
||||||
return this.token
|
return this.token
|
||||||
}
|
}
|
||||||
return localStorage.getItem('token')
|
return this.userType === 1
|
||||||
|
? localStorage.getItem('token')
|
||||||
|
: localStorage.getItem('accessToken')
|
||||||
},
|
},
|
||||||
|
|
||||||
getPermissions() {
|
getPermissions() {
|
||||||
@ -35,7 +39,9 @@ const useUserStore = defineStore({
|
|||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
changeUserType(num: number) {
|
||||||
|
this.userType = num
|
||||||
|
},
|
||||||
async profile() {
|
async profile() {
|
||||||
return UserApi.profile().then((ok) => {
|
return UserApi.profile().then((ok) => {
|
||||||
this.userInfo = ok.data
|
this.userInfo = ok.data
|
||||||
|
|||||||
15
ui/src/utils/clipboard.ts
Normal file
15
ui/src/utils/clipboard.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import Clipboard from 'vue-clipboard3'
|
||||||
|
import { MsgSuccess, MsgError } from '@/utils/message'
|
||||||
|
/*
|
||||||
|
复制粘贴
|
||||||
|
*/
|
||||||
|
export async function copyClick(info: string) {
|
||||||
|
const { toClipboard } = Clipboard()
|
||||||
|
try {
|
||||||
|
await toClipboard(info)
|
||||||
|
MsgSuccess('复制成功')
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e)
|
||||||
|
MsgError('复制失败')
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -49,3 +49,4 @@ export function realatedObject(list: any, val: string | number, attr: string) {
|
|||||||
const filterData: any = list.filter((item: any) => item[attr] === val)?.[0]
|
const filterData: any = list.filter((item: any) => item[attr] === val)?.[0]
|
||||||
return filterData || null
|
return filterData || null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -4,9 +4,14 @@
|
|||||||
<h4 class="title-decoration-1 mb-16">应用信息</h4>
|
<h4 class="title-decoration-1 mb-16">应用信息</h4>
|
||||||
<el-card shadow="never" class="overview-card">
|
<el-card shadow="never" class="overview-card">
|
||||||
<div class="title flex align-center">
|
<div class="title flex align-center">
|
||||||
<AppAvatar class="mr-12" shape="square" :size="32">
|
<AppAvatar
|
||||||
<img src="@/assets/icon_document.svg" style="width: 58%" alt="" />
|
v-if="detail?.name"
|
||||||
</AppAvatar>
|
:name="detail?.name"
|
||||||
|
pinyinColor
|
||||||
|
class="mr-12"
|
||||||
|
shape="square"
|
||||||
|
:size="32"
|
||||||
|
/>
|
||||||
<h4 class="ellipsis-1">{{ detail?.name }}</h4>
|
<h4 class="ellipsis-1">{{ detail?.name }}</h4>
|
||||||
<div class="ml-8" v-if="detail">
|
<div class="ml-8" v-if="detail">
|
||||||
<el-tag v-if="detail?.status" class="success-tag">运行中</el-tag>
|
<el-tag v-if="detail?.status" class="success-tag">运行中</el-tag>
|
||||||
@ -24,8 +29,8 @@
|
|||||||
{{ shareUrl }}
|
{{ shareUrl }}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<el-button type="primary" text>
|
<el-button type="primary" text @click="copyClick(shareUrl)">
|
||||||
<el-icon style="font-size: 13px"><CopyDocument /></el-icon>
|
<AppIcon iconName="app-copy"></AppIcon>
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
@ -37,14 +42,14 @@
|
|||||||
</span>
|
</span>
|
||||||
|
|
||||||
<el-button type="primary" text>
|
<el-button type="primary" text>
|
||||||
<el-icon style="font-size: 13px"><CopyDocument /></el-icon>
|
<AppIcon iconName="app-copy"></AppIcon>
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-4">
|
<div class="mt-4">
|
||||||
<span class="vertical-middle lighter"> API Secret: ************** </span>
|
<span class="vertical-middle lighter"> API Secret: ************** </span>
|
||||||
<span>
|
<span>
|
||||||
<el-button type="primary" text>
|
<el-button type="primary" text>
|
||||||
<el-icon style="font-size: 13px"><CopyDocument /></el-icon>
|
<AppIcon iconName="app-copy"></AppIcon>
|
||||||
</el-button>
|
</el-button>
|
||||||
</span>
|
</span>
|
||||||
<span>
|
<span>
|
||||||
@ -56,7 +61,7 @@
|
|||||||
</el-col> -->
|
</el-col> -->
|
||||||
</el-row>
|
</el-row>
|
||||||
<div class="mt-16">
|
<div class="mt-16">
|
||||||
<el-button type="primary"> 演示 </el-button>
|
<el-button type="primary"><a :href="shareUrl" target="_blank">演示</a></el-button>
|
||||||
<el-button @click="openDialog"> 嵌入第三方 </el-button>
|
<el-button @click="openDialog"> 嵌入第三方 </el-button>
|
||||||
</div>
|
</div>
|
||||||
</el-card>
|
</el-card>
|
||||||
@ -69,6 +74,7 @@ import { reactive, ref, watch, onMounted } from 'vue'
|
|||||||
import { useRouter, useRoute } from 'vue-router'
|
import { useRouter, useRoute } from 'vue-router'
|
||||||
import applicationApi from '@/api/application'
|
import applicationApi from '@/api/application'
|
||||||
import EmbedDialog from './components/EmbedDialog.vue'
|
import EmbedDialog from './components/EmbedDialog.vue'
|
||||||
|
import { copyClick } from '@/utils/clipboard'
|
||||||
import useStore from '@/stores'
|
import useStore from '@/stores'
|
||||||
const { application } = useStore()
|
const { application } = useStore()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
@ -76,6 +82,7 @@ const route = useRoute()
|
|||||||
|
|
||||||
const EmbedDialogRef = ref()
|
const EmbedDialogRef = ref()
|
||||||
const shareUrl = ref('')
|
const shareUrl = ref('')
|
||||||
|
const accessToken = ref('')
|
||||||
const detail = ref<any>(null)
|
const detail = ref<any>(null)
|
||||||
const apiKey = ref<any>(null)
|
const apiKey = ref<any>(null)
|
||||||
const {
|
const {
|
||||||
@ -85,10 +92,11 @@ const {
|
|||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
|
|
||||||
function openDialog() {
|
function openDialog() {
|
||||||
EmbedDialogRef.value.open()
|
EmbedDialogRef.value.open(accessToken.value)
|
||||||
}
|
}
|
||||||
function getAccessToken() {
|
function getAccessToken() {
|
||||||
application.asyncGetAccessToken(id, loading).then((res) => {
|
application.asyncGetAccessToken(id, loading).then((res) => {
|
||||||
|
accessToken.value = res?.data?.access_token
|
||||||
shareUrl.value = application.location + res?.data?.access_token
|
shareUrl.value = application.location + res?.data?.access_token
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-dialog title="添加关联数据集" v-model="dialogVisible" width="600">
|
<el-dialog title="添加关联数据集" v-model="dialogVisible" width="600">
|
||||||
<template #header="{ close, titleId, titleClass }">
|
<template #header="{ titleId, titleClass }">
|
||||||
<div class="my-header flex">
|
<div class="my-header flex">
|
||||||
<h4 :id="titleId" :class="titleClass">添加关联数据集</h4>
|
<h4 :id="titleId" :class="titleClass">添加关联数据集</h4>
|
||||||
<el-button link class="ml-16" @click="refresh">
|
<el-button link class="ml-16" @click="refresh">
|
||||||
|
|||||||
@ -7,8 +7,8 @@
|
|||||||
<div class="code border-t p-16">
|
<div class="code border-t p-16">
|
||||||
<div class="flex-between">
|
<div class="flex-between">
|
||||||
<span class="bold">复制以下代码进行嵌入</span>
|
<span class="bold">复制以下代码进行嵌入</span>
|
||||||
<el-button text>
|
<el-button text @click="copyClick(source1)">
|
||||||
<el-icon style="font-size: 13px"><CopyDocument /></el-icon>
|
<AppIcon iconName="app-copy"></AppIcon>
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-8">
|
<div class="mt-8">
|
||||||
@ -23,8 +23,8 @@
|
|||||||
<div class="code border-t p-16">
|
<div class="code border-t p-16">
|
||||||
<div class="flex-between">
|
<div class="flex-between">
|
||||||
<span class="bold">复制以下代码进行嵌入</span>
|
<span class="bold">复制以下代码进行嵌入</span>
|
||||||
<el-button text>
|
<el-button text @click="copyClick(source2)">
|
||||||
<el-icon style="font-size: 13px"><CopyDocument /></el-icon>
|
<AppIcon iconName="app-copy"></AppIcon>
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-8">
|
<div class="mt-8">
|
||||||
@ -38,48 +38,45 @@
|
|||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, watch } from 'vue'
|
import { ref, watch } from 'vue'
|
||||||
|
import { copyClick } from '@/utils/clipboard'
|
||||||
|
import useStore from '@/stores'
|
||||||
|
|
||||||
const props = defineProps({
|
const { application } = useStore()
|
||||||
data: {
|
|
||||||
type: Array<any>,
|
|
||||||
default: () => []
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const emit = defineEmits(['addData'])
|
const emit = defineEmits(['addData'])
|
||||||
|
|
||||||
const loading = ref(false)
|
|
||||||
const dialogVisible = ref<boolean>(false)
|
const dialogVisible = ref<boolean>(false)
|
||||||
const source1 = ref(`<iframe
|
|
||||||
src="https://udify.app/chatbot/ASkyzvhN5Z1h6k7g"
|
const source1 = ref('')
|
||||||
|
|
||||||
|
const source2 = ref('')
|
||||||
|
|
||||||
|
watch(dialogVisible, (bool) => {
|
||||||
|
if (!bool) {
|
||||||
|
source1.value = ''
|
||||||
|
source2.value = ''
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const open = (val: string) => {
|
||||||
|
source1.value = `<iframe
|
||||||
|
src="${application.location + val}"
|
||||||
style="width: 100%; height: 100%;"
|
style="width: 100%; height: 100%;"
|
||||||
frameborder="0"
|
frameborder="0"
|
||||||
allow="microphone">
|
allow="microphone">
|
||||||
</iframe>
|
</iframe>
|
||||||
`)
|
`
|
||||||
|
source2.value = `<script> window.difyChatbotConfig = {
|
||||||
const source2 = ref(`<script> window.difyChatbotConfig = {
|
token: "${val}"
|
||||||
token: '85FfbbzTpXzzr40X'
|
|
||||||
}
|
}
|
||||||
<\/script>
|
<\/script>
|
||||||
<script src="https://udify.app/embed.min.js"
|
<script src="https://udify.app/embed.min.js"
|
||||||
id="85FfbbzTpXzzr40X"
|
id="${val}"
|
||||||
defer>
|
defer>
|
||||||
<\/script>
|
<\/script>
|
||||||
`)
|
`
|
||||||
|
|
||||||
watch(dialogVisible, (bool) => {
|
|
||||||
if (!bool) {
|
|
||||||
loading.value = false
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const open = (checked: any) => {
|
|
||||||
dialogVisible.value = true
|
dialogVisible.value = true
|
||||||
}
|
}
|
||||||
const submitHandle = () => {
|
|
||||||
dialogVisible.value = false
|
|
||||||
}
|
|
||||||
|
|
||||||
defineExpose({ open })
|
defineExpose({ open })
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -36,6 +36,16 @@
|
|||||||
class="application-card cursor"
|
class="application-card cursor"
|
||||||
@click="router.push({ path: `/application/${item.id}/overview` })"
|
@click="router.push({ path: `/application/${item.id}/overview` })"
|
||||||
>
|
>
|
||||||
|
<template #icon>
|
||||||
|
<AppAvatar
|
||||||
|
v-if="item.name"
|
||||||
|
:name="item.name"
|
||||||
|
pinyinColor
|
||||||
|
class="mr-12"
|
||||||
|
shape="square"
|
||||||
|
:size="32"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
<div class="status-tag">
|
<div class="status-tag">
|
||||||
<el-tag v-if="item.status" class="success-tag">运行中</el-tag>
|
<el-tag v-if="item.status" class="success-tag">运行中</el-tag>
|
||||||
<el-tag v-else class="warning-tag">已停用</el-tag>
|
<el-tag v-else class="warning-tag">已停用</el-tag>
|
||||||
@ -44,7 +54,7 @@
|
|||||||
<template #footer>
|
<template #footer>
|
||||||
<div class="footer-content">
|
<div class="footer-content">
|
||||||
<el-tooltip effect="dark" content="演示" placement="top">
|
<el-tooltip effect="dark" content="演示" placement="top">
|
||||||
<el-button text @click.stop>
|
<el-button text @click.stop @click="getAccessToken(item.id)">
|
||||||
<AppIcon iconName="app-view"></AppIcon>
|
<AppIcon iconName="app-view"></AppIcon>
|
||||||
</el-button>
|
</el-button>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
@ -71,7 +81,9 @@
|
|||||||
<span>运行中</span>
|
<span>运行中</span>
|
||||||
<!-- <el-switch v-model="item.status" @change="changeState($event, item)" /> -->
|
<!-- <el-switch v-model="item.status" @change="changeState($event, item)" /> -->
|
||||||
</div>
|
</div>
|
||||||
<el-dropdown-item divided @click="deleteApplication(item)">删除</el-dropdown-item>
|
<el-dropdown-item divided @click="deleteApplication(item)"
|
||||||
|
>删除</el-dropdown-item
|
||||||
|
>
|
||||||
</el-dropdown-menu>
|
</el-dropdown-menu>
|
||||||
</template>
|
</template>
|
||||||
</el-dropdown>
|
</el-dropdown>
|
||||||
@ -90,6 +102,8 @@ import applicationApi from '@/api/application'
|
|||||||
import type { pageRequest } from '@/api/type/common'
|
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 { useRouter } from 'vue-router'
|
||||||
|
import useStore from '@/stores'
|
||||||
|
const { application } = useStore()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
@ -109,15 +123,17 @@ function search() {
|
|||||||
getList()
|
getList()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getAccessToken(id: string) {
|
||||||
|
application.asyncGetAccessToken(id, loading).then((res) => {
|
||||||
|
window.open(application.location + res?.data?.access_token)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
function deleteApplication(row: any) {
|
function deleteApplication(row: any) {
|
||||||
MsgConfirm(
|
MsgConfirm(`是否删除应用:${row.name} ?`, `删除后该应用将不再提供服务,请谨慎操作。`, {
|
||||||
`是否删除应用:${row.name} ?`,
|
|
||||||
`删除后该应用将不再提供服务,请谨慎操作。`,
|
|
||||||
{
|
|
||||||
confirmButtonText: '删除',
|
confirmButtonText: '删除',
|
||||||
confirmButtonClass: 'danger'
|
confirmButtonClass: 'danger'
|
||||||
}
|
})
|
||||||
)
|
|
||||||
.then(() => {
|
.then(() => {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
applicationApi
|
applicationApi
|
||||||
|
|||||||
@ -1,13 +1,45 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="chat">
|
<div class="chat">
|
||||||
<div class="chat__header">
|
<div class="chat__header">
|
||||||
<div class="chat-width"><h2 class="ml-24">111</h2></div>
|
<div class="chat-width">
|
||||||
|
<h2 class="ml-24">{{ applicationDetail?.name }}</h2>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="chat__main chat-width" v-loading="loading">
|
||||||
|
<AiDialog :data="applicationDetail" :appId="applicationDetail?.id"></AiDialog>
|
||||||
</div>
|
</div>
|
||||||
<div class="chat__main chat-width"><AiDialog></AiDialog></div>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { reactive, ref, watch, onMounted } from 'vue'
|
||||||
|
import { useRouter, useRoute } from 'vue-router'
|
||||||
import AiDialog from '@/components/ai-dialog/index.vue'
|
import AiDialog from '@/components/ai-dialog/index.vue'
|
||||||
|
import applicationApi from '@/api/application'
|
||||||
|
import useStore from '@/stores'
|
||||||
|
const route = useRoute()
|
||||||
|
const {
|
||||||
|
params: { accessToken }
|
||||||
|
} = route as any
|
||||||
|
|
||||||
|
const { application, user } = useStore()
|
||||||
|
|
||||||
|
const loading = ref(false)
|
||||||
|
const applicationDetail = ref<any>({})
|
||||||
|
|
||||||
|
function getAccessToken(token: string) {
|
||||||
|
application.asyncAppAuthentication(token, loading).then((res) => {
|
||||||
|
getProfile()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
function getProfile() {
|
||||||
|
applicationApi.getProfile(loading).then((res) => {
|
||||||
|
applicationDetail.value = res.data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
onMounted(() => {
|
||||||
|
user.changeUserType(2)
|
||||||
|
getAccessToken(accessToken)
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.chat {
|
.chat {
|
||||||
|
|||||||
@ -3,33 +3,31 @@
|
|||||||
<div class="template-manage flex main-calc-height">
|
<div class="template-manage flex main-calc-height">
|
||||||
<div class="template-manage__left p-8 border-r">
|
<div class="template-manage__left p-8 border-r">
|
||||||
<h4 class="p-16">供应商</h4>
|
<h4 class="p-16">供应商</h4>
|
||||||
|
|
||||||
<common-list
|
<common-list
|
||||||
v-model="active_provider"
|
|
||||||
:data="provider_list"
|
:data="provider_list"
|
||||||
class="mt-8"
|
class="mt-8"
|
||||||
v-loading="loading"
|
v-loading="loading"
|
||||||
|
@click="clickListHandle"
|
||||||
>
|
>
|
||||||
<template #prefix>
|
<template #default="{ row, index }">
|
||||||
<div class="flex">
|
<div class="flex" v-if="index === 0">
|
||||||
<AppIcon
|
<AppIcon
|
||||||
style="height: 24px; width: 24px"
|
|
||||||
class="mr-8"
|
class="mr-8"
|
||||||
:iconName="active_provider ? 'app-all-menu' : 'app-all-menu-active'"
|
style="height: 20px; width: 20px"
|
||||||
|
:iconName="active_provider === row ? 'app-all-menu-active' : 'app-all-menu'"
|
||||||
></AppIcon>
|
></AppIcon>
|
||||||
<span>全部模型</span>
|
<span>全部模型</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
<div class="flex" v-else>
|
||||||
<template #default="{ row }">
|
<span :innerHTML="row.icon" alt="" style="height: 20px; width: 20px" class="mr-8" />
|
||||||
<div class="flex">
|
|
||||||
<span :innerHTML="row.icon" alt="" style="height: 24px; width: 24px" class="mr-8" />
|
|
||||||
<span>{{ row.name }}</span>
|
<span>{{ row.name }}</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</common-list>
|
</common-list>
|
||||||
</div>
|
</div>
|
||||||
<div class="template-manage__right p-24" v-loading="list_model_loading">
|
<div class="template-manage__right p-24" v-loading="list_model_loading">
|
||||||
<h3 v-if="active_provider">{{ active_provider.name }}</h3>
|
<h3>{{ active_provider?.name }}</h3>
|
||||||
<h3 v-else>全部模型</h3>
|
|
||||||
<div class="flex-between mt-8">
|
<div class="flex-between mt-8">
|
||||||
<el-button type="primary" @click="openCreateModel(active_provider)">创建模型</el-button>
|
<el-button type="primary" @click="openCreateModel(active_provider)">创建模型</el-button>
|
||||||
<el-input
|
<el-input
|
||||||
@ -66,6 +64,12 @@ import { splitArray } from '@/utils/common'
|
|||||||
import CreateModel from '@/views/template/component/CreateModel.vue'
|
import CreateModel from '@/views/template/component/CreateModel.vue'
|
||||||
import SelectProvider from '@/views/template/component/SelectProvider.vue'
|
import SelectProvider from '@/views/template/component/SelectProvider.vue'
|
||||||
|
|
||||||
|
const allObj = {
|
||||||
|
icon: '',
|
||||||
|
provider: '',
|
||||||
|
name: '全部模型'
|
||||||
|
}
|
||||||
|
|
||||||
const loading = ref<boolean>(false)
|
const loading = ref<boolean>(false)
|
||||||
|
|
||||||
const active_provider = ref<Provider>()
|
const active_provider = ref<Provider>()
|
||||||
@ -81,8 +85,13 @@ const model_split_list = computed(() => {
|
|||||||
const createModelRef = ref<InstanceType<typeof CreateModel>>()
|
const createModelRef = ref<InstanceType<typeof CreateModel>>()
|
||||||
const selectProviderRef = ref<InstanceType<typeof SelectProvider>>()
|
const selectProviderRef = ref<InstanceType<typeof SelectProvider>>()
|
||||||
|
|
||||||
|
const clickListHandle = (item: Provider) => {
|
||||||
|
active_provider.value = item
|
||||||
|
list_model()
|
||||||
|
}
|
||||||
|
|
||||||
const openCreateModel = (provider?: Provider) => {
|
const openCreateModel = (provider?: Provider) => {
|
||||||
if (provider) {
|
if (provider && provider.provider) {
|
||||||
createModelRef.value?.open(provider)
|
createModelRef.value?.open(provider)
|
||||||
} else {
|
} else {
|
||||||
selectProviderRef.value?.open()
|
selectProviderRef.value?.open()
|
||||||
@ -90,19 +99,17 @@ const openCreateModel = (provider?: Provider) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const list_model = () => {
|
const list_model = () => {
|
||||||
const params = active_provider.value ? { provider: active_provider.value.provider } : {}
|
const params = active_provider.value?.provider ? { provider: active_provider.value.provider } : {}
|
||||||
ModelApi.getModel({ ...model_search_form.value, ...params }, list_model_loading).then((ok) => {
|
ModelApi.getModel({ ...model_search_form.value, ...params }, list_model_loading).then((ok) => {
|
||||||
model_list.value = ok.data
|
model_list.value = ok.data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(active_provider, list_model, {
|
|
||||||
immediate: true
|
|
||||||
})
|
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
ModelApi.getProvider(loading).then((ok) => {
|
ModelApi.getProvider(loading).then((ok) => {
|
||||||
provider_list.value = [...ok.data]
|
active_provider.value = allObj
|
||||||
|
provider_list.value = [allObj, ...ok.data]
|
||||||
|
list_model()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user