Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 24 additions & 19 deletions data-agent-frontend/src/services/fileUpload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,40 +13,45 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import axios from 'axios';
import { ApiResponse } from '@/services/common.ts';

/**
* 业务API服务
* 封装所有业务相关的API调用
*/

interface UploadResponse {
success: boolean;
message?: string;
url?: string;
interface FileStorage {
id: number;
filePath?: string;
url: string;
filename?: string;
}

export type FileUploadResult = ApiResponse<FileStorage>;

// 文件上传API
export const fileUploadApi = {
// 上传头像
uploadAvatar(file: File): Promise<UploadResponse> {
async uploadAvatar(file: File): Promise<FileStorage | null> {
const formData = new FormData();
formData.append('file', file);

const url = '/api/upload/avatar';
return fetch(url, {
method: 'POST',
body: formData,
}).then(async response => {
if (!response.ok) {
const text = await response.text().catch(() => '');
throw new Error(`Upload failed: ${response.status} ${text}`);
try {
const response = await axios.post<FileUploadResult>(url, formData, {
headers: {
'Content-Type': 'multipart/form-data',
},
});
if (response.data.success) {
return response.data.data ?? null;
}
const ct = response.headers.get('content-type') || '';
if (ct.includes('application/json')) {
return await response.json();
throw new Error(response.data.message);
} catch (error) {
if (axios.isAxiosError(error) && error.response?.status === 404) {
return null;
}
const text = await response.text();
return { success: true, message: 'ok', url: text };
});
throw error;
}
},
};
26 changes: 14 additions & 12 deletions data-agent-frontend/src/views/AgentCreate.vue
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,18 @@
<div class="avatar-controls">
<div class="avatar-buttons">
<el-button @click="regenerateAvatar" size="large">
<el-icon><Refresh /></el-icon>
<el-icon>
<Refresh />
</el-icon>
重新生成
</el-button>
<el-button @click="triggerFileUpload" :disabled="uploading" size="large">
<el-icon v-if="!uploading"><Upload /></el-icon>
<el-icon v-if="uploading"><Loading /></el-icon>
<el-icon v-if="!uploading">
<Upload />
</el-icon>
<el-icon v-if="uploading">
<Loading />
</el-icon>
{{ uploading ? '上传中...' : '上传图片' }}
</el-button>
<input
Expand Down Expand Up @@ -165,10 +171,10 @@
</template>

<script lang="ts">
import { defineComponent, reactive, ref, onMounted } from 'vue';
import { defineComponent, onMounted, reactive, ref } from 'vue';
import { useRouter } from 'vue-router';
import { ElMessage } from 'element-plus';
import { Plus, Refresh, Upload, Loading } from '@element-plus/icons-vue';
import { Loading, Plus, Refresh, Upload } from '@element-plus/icons-vue';
import BaseLayout from '../layouts/BaseLayout.vue';
import agentService from '@/services/agent';
import { fileUploadApi } from '@/services/fileUpload';
Expand Down Expand Up @@ -272,13 +278,9 @@
// 上传文件
const response = await fileUploadApi.uploadAvatar(file);

if (response.success) {
// 上传成功,使用服务器返回的URL
agentForm.avatar = response.url;
ElMessage.success('头像上传成功');
} else {
throw new Error(response.message || '上传失败');
}
// 上传成功,使用服务器返回的URL
agentForm.avatar = response.url;
ElMessage.success('头像上传成功');
} catch (error) {
console.error('头像上传失败:', error);
ElMessage.error('头像上传失败: ' + (error instanceof Error ? error.message : '未知错误'));
Expand Down
61 changes: 37 additions & 24 deletions data-agent-frontend/src/views/AgentDetail.vue
Original file line number Diff line number Diff line change
Expand Up @@ -73,49 +73,67 @@
>
<el-menu-item-group title="基本信息">
<el-menu-item index="basic">
<el-icon><InfoFilled /></el-icon>
<el-icon>
<InfoFilled />
</el-icon>
基本信息
</el-menu-item>
</el-menu-item-group>
<el-menu-item-group title="数据源配置">
<el-menu-item index="datasource">
<el-icon><Coin /></el-icon>
<el-icon>
<Coin />
</el-icon>
数据源配置
</el-menu-item>
</el-menu-item-group>
<el-menu-item-group title="PROMPT配置">
<el-menu-item index="prompt">
<el-icon><ChatLineSquare /></el-icon>
<el-icon>
<ChatLineSquare />
</el-icon>
自定义 PROMPT 配置
</el-menu-item>
</el-menu-item-group>
<el-menu-item-group title="知识配置">
<el-menu-item index="agent-knowledge">
<el-icon><Document /></el-icon>
<el-icon>
<Document />
</el-icon>
智能体知识配置
</el-menu-item>
<el-menu-item index="business-knowledge">
<el-icon><User /></el-icon>
<el-icon>
<User />
</el-icon>
业务知识配置
</el-menu-item>
<el-menu-item index="semantic-model">
<el-icon><Suitcase /></el-icon>
<el-icon>
<Suitcase />
</el-icon>
语义模型配置
</el-menu-item>
</el-menu-item-group>
<el-menu-item-group title="预设问题管理">
<el-menu-item index="preset-questions">
<el-icon><Setting /></el-icon>
<el-icon>
<Setting />
</el-icon>
预设问题管理
</el-menu-item>
</el-menu-item-group>
<el-menu-item-group title="运行与发布">
<el-menu-item index="go-run">
<el-icon><VideoPlay /></el-icon>
<el-icon>
<VideoPlay />
</el-icon>
前往运行页面
</el-menu-item>
<el-menu-item index="access-api">
<el-icon><Connection /></el-icon>
<el-icon>
<Connection />
</el-icon>
访问 API
</el-menu-item>
</el-menu-item-group>
Expand Down Expand Up @@ -161,21 +179,21 @@
</template>

<script lang="ts">
import { ref, defineComponent, Ref, onMounted } from 'vue';
import { defineComponent, onMounted, Ref, ref } from 'vue';
import { useRouter } from 'vue-router';
import { ElMessage } from 'element-plus';
import AgentService from '@/services/agent';
import AgentService, { Agent } from '@/services/agent';
import {
ArrowLeft,
InfoFilled,
Coin,
ChatLineSquare,
User,
Suitcase,
Setting,
VideoPlay,
Coin,
Connection,
Document,
InfoFilled,
Setting,
Suitcase,
User,
VideoPlay,
} from '@element-plus/icons-vue';
import BaseLayout from '@/layouts/BaseLayout.vue';
import AgentBaseSetting from '@/components/agent/BaseSetting.vue';
Expand All @@ -187,7 +205,6 @@
import AgentDataSourceConfig from '@/components/agent/DataSourceConfig.vue';
import AgentKnowledgeConfig from '@/components/agent/AgentKnowledgeConfig.vue';
import NotFound from '@/views/NotFound.vue';
import { Agent } from '@/services/agent';
import { fileUploadApi } from '@/services/fileUpload';

export default defineComponent({
Expand Down Expand Up @@ -273,12 +290,8 @@

const response = await fileUploadApi.uploadAvatar(file);

if (response.success) {
agent.value.avatar = response.url;
ElMessage.success('头像上传成功');
} else {
throw new Error(response.message || '上传失败');
}
agent.value.avatar = response.url;
ElMessage.success('头像上传成功');
} catch (error) {
ElMessage.error('头像上传失败: ' + (error instanceof Error ? error.message : '未知错误'));
agent.value.avatar = originalHeaderAvatar.value;
Expand Down
Loading
Loading