Skip to content

Commit

Permalink
feat: role search/new function
Browse files Browse the repository at this point in the history
  • Loading branch information
orangelckc committed Mar 15, 2023
1 parent 1ca99f2 commit a587ae0
Show file tree
Hide file tree
Showing 13 changed files with 193 additions and 111 deletions.
16 changes: 7 additions & 9 deletions src/App.vue
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
<script setup lang="ts">
import { appWindow } from '@tauri-apps/api/window'
import { initSQL } from '@/sqls'
import { useSettingsStore, useRecordStore, useRoleStore } from '@/stores'
import { useSettingsStore, useSessionStore, useRoleStore } from '@/stores'
// TODO: 首次加载有问题,获取不到初始化的角色列表
initSQL()
const { themeClass, isFix, shortcutKey } = storeToRefs(useSettingsStore())
const { currentRecord } = storeToRefs(useRecordStore())
const { currentSession } = storeToRefs(useSessionStore())
const { currentRole } = storeToRefs(useRoleStore())
const windowFocused = ref(true)
Expand Down Expand Up @@ -35,10 +35,10 @@ onMounted(async () => {
</div>

<div class="flex-1 cursor-default overflow-auto">
<template v-if="currentRecord">
<template v-if="currentSession">
123132
<!-- <div
class="flex items-start p-2"
class="flex p-2 items-start"
v-for="(item, index) of currentRecord.data?.slice(1)"
:key="index"
>
Expand Down Expand Up @@ -75,16 +75,14 @@ onMounted(async () => {

<div class="flex cursor-default flex-col gap-2 pt-2">
<div class="text-6 relative flex justify-end gap-4">
<div class="text-4 left-50% top-50% -translate-1/2 absolute">
<div class="top-50% left-50% text-4 -translate-1/2 absolute">
正在与 <span class="mark">{{ currentRole?.name }}</span> 对话
</div>

<!-- <Function /> -->

<!-- <Settings /> -->
<Function />
</div>

<!-- <Input /> -->
<Input />
</div>
</div>
</template>
4 changes: 2 additions & 2 deletions src/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { fetch, Body } from '@tauri-apps/api/http'
import { dialogErrorMessage } from '@/utils'
import type { FetchOptions } from '@tauri-apps/api/http'
import type { RecordData } from '@/types'
import { useSettingsStore, useRecordStore } from '@/stores'
import { useSettingsStore, useSessionStore } from '@/stores'

/**
* 请求总入口
Expand Down Expand Up @@ -43,7 +43,7 @@ export const request = async (url: string, options?: FetchOptions) => {
*/
export const getOpenAIResultApi = async () => {
const { apiKey } = useSettingsStore()
const { currentRecord } = useRecordStore()
const { currentRecord } = useSessionStore()

return await request(import.meta.env.VITE_OPEN_AI_URL, {
method: 'POST',
Expand Down
2 changes: 1 addition & 1 deletion src/components/Avatar/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const props = withDefaults(defineProps<{ value?: string }>(), {
value: import.meta.env.VITE_APP_NAME
})
const avatar = computed(() => multiAvatar(props.value))
const avatar = computed(() => multiAvatar(props.value || '默认头像'))
</script>

<template>
Expand Down
6 changes: 4 additions & 2 deletions src/components/Function/components/ShortcutKey.vue
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
<script setup lang="ts">
import { Icon } from '@arco-design/web-vue'
import { IconCloseCircleFill } from '@arco-design/web-vue/es/icon'
import { useShortcutKeyStore } from '@/stores'
import { useSettingsStore } from '@/stores'
import { hotkeys, isHotKey, getKeyIcon, getKeySymbol } from '@/utils'
const IconFont = Icon.addFromIconFontCn({
src: import.meta.env.VITE_ICON_FONT_URL
})
const { shortcutKey, setupComplete } = storeToRefs(useShortcutKeyStore())
const { shortcutKey, isBinding: setupComplete } = storeToRefs(
useSettingsStore()
)
const lastShortcutKey = computed(() => shortcutKey.value.at(-1) || '')
Expand Down
12 changes: 6 additions & 6 deletions src/components/Function/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ import {
IconHistory,
IconSettings
} from '@arco-design/web-vue/es/icon'
import { useRecordStore } from '@/stores'
import { useSessionStore } from '@/stores'
import { getArrayLength } from '@/utils'
const recordStore = useRecordStore()
const recordStore = useSessionStore()
const { createNewRecord, getAiMessage, deleteRecord } = recordStore
const { currentRecord, isThinking } = storeToRefs(recordStore)
const { currentSession, isThinking } = storeToRefs(recordStore)
const modalVisible = ref(false)
const setModalVisible = () => {
Expand All @@ -23,20 +23,20 @@ const functions = computed(() => [
{
content: '新建对话',
icon: IconPlusCircle,
disabled: !!currentRecord,
disabled: !!currentSession,
handleClick: createNewRecord
},
{
content: '重新回答',
icon: IconRefresh,
disabled:
isThinking.value || !(getArrayLength(currentRecord.value?.data) > 2),
isThinking.value || !(getArrayLength(currentSession.value?.data) > 2),
handleClick: () => getAiMessage()
},
{
content: '清空对话',
icon: IconDelete,
disabled: !!currentRecord,
disabled: !!currentSession,
handleClick: () => deleteRecord()
},
{
Expand Down
118 changes: 64 additions & 54 deletions src/components/Input/components/RoleList.vue
Original file line number Diff line number Diff line change
@@ -1,45 +1,62 @@
<script lang="ts" setup>
import { IconEdit, IconCheck, IconDelete } from '@arco-design/web-vue/es/icon'
import {
IconEdit,
IconCheck,
IconDelete,
IconClose
} from '@arco-design/web-vue/es/icon'
import { useRoleStore } from '@/stores'
import { DEFAULT_ROLE } from '@/constants'
import type { TablePayload } from '@/types'
import type { RolePayload } from '@/types'
const roleStore = useRoleStore()
const { addRole, updateRole, deleteRole } = roleStore
const { currentRole, roleList } = storeToRefs(roleStore)
const isEdit = ref(false)
const editItem = ref<TablePayload>({})
const handleEdit = (data: TablePayload) => {
handleUpdate()
isEdit.value = true
editItem.value = data
const { updateRole, deleteRole, addRole, getRoleList } = roleStore
const { currentRole, showList, isShow, isAddNew } = storeToRefs(roleStore)
const handleUpdate = (item: RolePayload) => {
if (isAddNew.value) {
const { name, description } = item
addRole({ name, description })
} else {
if (!item.id) return
item.isEdit = false
updateRole(item)
}
}
const handleUpdate = () => {
if (!editItem.value.id) return
const handleSelect = (role: RolePayload) => {
isShow.value = false
currentRole.value = role
}
isEdit.value = false
updateRole(editItem.value)
const handleAdd = () => {
isAddNew.value = true
// TODO 这里需要优化,自动聚焦到输入框
}
watch(currentRole, handleUpdate)
const handleHide = () => {
// 判断是否有正在编辑的角色
const isEdit = showList.value.some((item) => item.isEdit)
if (isEdit) return
isShow.value = false
}
</script>
<!-- TODO:优化代码和 css 样式 -->
<!-- TODO:输入内容的非空判断 -->
<!-- TODO:修改当前选中的,有 bug -->
<template>
<a-popover
title="请选择对话的角色"
trigger="click"
:popup-visible="isShow"
class="role-popover w-full"
@click="isShow = true"
@popup-visible-change="handleHide"
>
<template #title>
<div class="flex items-center justify-between">
<span>请选择对话的角色</span>
<a-button type="outline">添加角色</a-button>
<span>{{ isAddNew ? '请填写信息' : '请选择对话的角色' }}</span>
<a-button type="outline" @click="handleAdd" v-if="!isAddNew"
>添加角色</a-button
>
</div>
</template>

Expand All @@ -50,60 +67,53 @@ watch(currentRole, handleUpdate)
<template #content>
<ul class="role-list">
<li
class="bordered-top flex cursor-pointer items-center gap-4 p-4 text-[var(--color-text-1)]"
:style="{
background:
currentRole?.id === item.id
? 'rgb(var(--blue-6), 0.2)'
: 'transparent'
class="flex cursor-pointer items-center gap-4 rounded-t bg-transparent p-4 text-[var(--color-text-1)] hover:bg-red-100"
:class="{
'bg-blue-200!': currentRole?.id === item.id
}"
v-for="item in roleList"
v-for="item in showList"
:key="item.id"
@click="currentRole = item"
@click="item.isEdit ? '' : handleSelect(item)"
>
<div class="flex flex-1 items-center gap-4">
<Avatar class="w-10!" :value="item.name" />
<div class="flex flex-1 flex-col gap-2">
<a-input
v-model="editItem.name"
v-model="item.name"
placeholder="请输入角色名称"
allow-clear
v-if="isEdit && editItem.id === item.id"
@click="(e: any) => e.stopPropagation()"
v-if="item.isEdit"
@click.stop
/>
<span v-else>
{{ item.name }}
</span>
<a-textarea
v-model="editItem.description"
v-model="item.description"
placeholder="请输入角色描述"
auto-size
allow-clear
v-if="isEdit && editItem.id === item.id"
@click="(e: any) => e.stopPropagation()"
v-if="item.isEdit"
@click.stop
></a-textarea>
<span v-else>
{{ item.description }}
</span>
</div>
</div>
<div
class="text-5 flex gap-2"
v-if="
item.name !== DEFAULT_ROLE.name ||
item.description !== DEFAULT_ROLE.description
"
@click="(e) => e.stopPropagation()"
>
<IconCheck
@click="handleUpdate"
v-if="isEdit && editItem.id === item.id"
/>
<IconEdit @click="handleEdit(item)" v-else />
<!-- TODO:编辑的时候变成 x -->
<IconDelete @click="deleteRole(item.id!)" />
<!-- TODO 这里我在在表里新增一个字is_default,更方便处理 -->
<div v-if="!item.is_default" @click.stop>
<div v-if="!item.isEdit" class="text-5 flex gap-5">
<IconEdit @click="item.isEdit = true" />
<IconDelete @click="deleteRole(item.id!)" />
</div>
<div v-else class="text-5 flex gap-5">
<IconCheck @click="handleUpdate(item)" />
<IconClose @click="getRoleList" />
</div>
</div>
</li>
</ul>
Expand All @@ -114,7 +124,7 @@ watch(currentRole, handleUpdate)
<style lang="scss">
.role-popover {
.arco-trigger-content {
@apply flex max-h-[calc(100vh-56px)] flex-col rounded-t-xl px-0 py-4;
@apply flex max-h-[calc(100vh-56px)] flex-col rounded-t-xl py-4 px-0;
.arco-popover-title {
@apply p-4 pt-0;
Expand Down
24 changes: 20 additions & 4 deletions src/components/Input/index.vue
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
<script lang="ts" setup>
import { useRecordStore } from '@/stores'
import { useSessionStore, useRoleStore } from '@/stores'
const recordStore = useRecordStore()
const recordStore = useSessionStore()
const { getAiMessage } = recordStore
const { isThinking } = storeToRefs(recordStore)
const roleStore = useRoleStore()
const { getFilterRoleList } = roleStore
const { currentRole } = storeToRefs(roleStore)
const textAreaElement = ref<HTMLTextAreaElement | null>(null)
const textAreaValue = ref('')
Expand All @@ -26,6 +30,15 @@ const onKeydown = (event: KeyboardEvent) => {
}
}
watch(textAreaValue, (value) => {
getFilterRoleList(value)
})
watch(currentRole, () => {
textAreaValue.value = ''
textAreaElement.value?.focus()
})
onMounted(() => {
// appWindow.onFocusChanged(() => {
// textAreaElement.value?.focus()
Expand All @@ -44,14 +57,16 @@ onMounted(() => {
v-model="textAreaValue"
:disabled="isThinking"
@keydown="onKeydown"
auto-size
clearable
></a-textarea>
</div>
</template>

<style lang="scss" scoped>
.app-input {
.arco-textarea-wrapper {
height: 32px;
// height: 32px;
transition: all 0.3s;
Expand All @@ -61,7 +76,8 @@ onMounted(() => {
border-color: var(--color-neutral-4);
}
&.arco-textarea-focus {
height: 96px;
max-height: 96px;
overflow-y: scroll;
border-color: rgb(var(--arcoblue-6));
border-radius: 0;
Expand Down
4 changes: 2 additions & 2 deletions src/components/Session/index.vue
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<script setup lang="ts">
import { useSettingsStore, useRecordStore, useRoleStore } from '@/stores'
import { useSettingsStore, useSessionStore, useRoleStore } from '@/stores'
const { uuid } = storeToRefs(useSettingsStore())
const { currentRecord } = storeToRefs(useRecordStore())
const { currentRecord } = storeToRefs(useSessionStore())
const { currentRole } = storeToRefs(useRoleStore())
</script>

Expand Down

0 comments on commit a587ae0

Please sign in to comment.