feat: model set avatar

This commit is contained in:
archer 2023-04-28 10:06:14 +08:00
parent 606105d633
commit 08ae4073bd
No known key found for this signature in database
GPG Key ID: 166CA6BF2383B2BB
6 changed files with 61 additions and 8 deletions

View File

@ -90,9 +90,6 @@ export const theme = extendTheme({
fonts: { fonts: {
body: '-apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol"' body: '-apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol"'
}, },
fontWeights: {
bold: 500
},
breakpoints: { breakpoints: {
sm: '900px', sm: '900px',
md: '1200px', md: '1200px',

View File

@ -9,7 +9,7 @@ import { authModel } from '@/service/utils/auth';
/* 获取我的模型 */ /* 获取我的模型 */
export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) { export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
try { try {
const { name, search, share, service, security, systemPrompt, temperature } = const { name, avatar, search, share, service, security, systemPrompt, temperature } =
req.body as ModelUpdateParams; req.body as ModelUpdateParams;
const { modelId } = req.query as { modelId: string }; const { modelId } = req.query as { modelId: string };
const { authorization } = req.headers; const { authorization } = req.headers;
@ -40,6 +40,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
}, },
{ {
name, name,
avatar,
systemPrompt, systemPrompt,
temperature, temperature,
'share.isShare': share.isShare, 'share.isShare': share.isShare,

View File

@ -1,4 +1,4 @@
import React, { useState } from 'react'; import React, { useState, useCallback } from 'react';
import { import {
Box, Box,
Card, Card,
@ -15,7 +15,8 @@ import {
Button, Button,
Select, Select,
Grid, Grid,
Switch Switch,
Image
} from '@chakra-ui/react'; } from '@chakra-ui/react';
import { QuestionOutlineIcon } from '@chakra-ui/icons'; import { QuestionOutlineIcon } from '@chakra-ui/icons';
import type { ModelSchema } from '@/types/mongoSchema'; import type { ModelSchema } from '@/types/mongoSchema';
@ -23,6 +24,9 @@ import { UseFormReturn } from 'react-hook-form';
import { modelList, ModelVectorSearchModeMap } from '@/constants/model'; import { modelList, ModelVectorSearchModeMap } from '@/constants/model';
import { formatPrice } from '@/utils/user'; import { formatPrice } from '@/utils/user';
import { useConfirm } from '@/hooks/useConfirm'; import { useConfirm } from '@/hooks/useConfirm';
import { useSelectFile } from '@/hooks/useSelectFile';
import { useToast } from '@/hooks/useToast';
import { fileToBase64 } from '@/utils/file';
const ModelEditForm = ({ const ModelEditForm = ({
formHooks, formHooks,
@ -40,11 +44,50 @@ const ModelEditForm = ({
}); });
const { register, setValue, getValues } = formHooks; const { register, setValue, getValues } = formHooks;
const [refresh, setRefresh] = useState(false); const [refresh, setRefresh] = useState(false);
const { File, onOpen: onOpenSelectFile } = useSelectFile({
fileType: '.jpg,.png',
multiple: false
});
const { toast } = useToast();
const onSelectFile = useCallback(
async (e: File[]) => {
const file = e[0];
if (!file) return;
if (file.size > 100 * 1024) {
return toast({
title: '头像需小于 100kb',
status: 'warning'
});
}
const base64 = (await fileToBase64(file)) as string;
setValue('avatar', base64);
setRefresh((state) => !state);
},
[setValue, toast]
);
return ( return (
<> <>
<Card p={4}> <Card p={4}>
<Box fontWeight={'bold'}></Box> <Box fontWeight={'bold'}></Box>
<Flex mt={4} alignItems={'center'}>
<Box flex={'0 0 80px'} w={0}>
:
</Box>
<Image
src={getValues('avatar')}
alt={'avatar'}
w={'36px'}
h={'36px'}
objectFit={'contain'}
cursor={'pointer'}
title={'点击切换头像'}
onClick={onOpenSelectFile}
/>
</Flex>
<FormControl mt={4}> <FormControl mt={4}>
<Flex alignItems={'center'}> <Flex alignItems={'center'}>
<Box flex={'0 0 80px'} w={0}> <Box flex={'0 0 80px'} w={0}>
@ -167,7 +210,7 @@ const ModelEditForm = ({
<Box mt={4}> <Box mt={4}>
<Box mb={1}></Box> <Box mb={1}></Box>
<Textarea <Textarea
rows={6} rows={8}
maxLength={-1} maxLength={-1}
isDisabled={!isOwner} isDisabled={!isOwner}
placeholder={ placeholder={
@ -235,6 +278,7 @@ const ModelEditForm = ({
</Grid> </Grid>
</Card> </Card>
)} )}
<File onSelect={onSelectFile} />
{/* <Card p={4}> {/* <Card p={4}>
<Box fontWeight={'bold'}></Box> <Box fontWeight={'bold'}></Box>

View File

@ -85,6 +85,7 @@ const ModelDetail = ({ modelId }: { modelId: string }) => {
try { try {
await putModelById(data._id, { await putModelById(data._id, {
name: data.name, name: data.name,
avatar: data.avatar,
systemPrompt: data.systemPrompt, systemPrompt: data.systemPrompt,
temperature: data.temperature, temperature: data.temperature,
search: data.search, search: data.search,

View File

@ -2,6 +2,7 @@ import { ModelStatusEnum } from '@/constants/model';
import type { ModelSchema } from './mongoSchema'; import type { ModelSchema } from './mongoSchema';
export interface ModelUpdateParams { export interface ModelUpdateParams {
name: string; name: string;
avatar: string;
systemPrompt: string; systemPrompt: string;
temperature: number; temperature: number;
search: ModelSchema['search']; search: ModelSchema['search'];

View File

@ -155,7 +155,7 @@ export const splitText = ({
slideLen: number; slideLen: number;
}) => { }) => {
const textArr = const textArr =
text.match(/[!?。\n.]+|[^\s]+/g)?.filter((item) => { text.split(/(?<=[。!?\.!\?\n])/g)?.filter((item) => {
const text = item.replace(/(\\n)/g, '\n').trim(); const text = item.replace(/(\\n)/g, '\n').trim();
if (text && text !== '\n') return true; if (text && text !== '\n') return true;
return false; return false;
@ -188,3 +188,12 @@ export const splitText = ({
const result = chunks.map((item) => item.arr.join('')); const result = chunks.map((item) => item.arr.join(''));
return result; return result;
}; };
export const fileToBase64 = (file: File) => {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => resolve(reader.result);
reader.onerror = (error) => reject(error);
});
};