'frontendadd'

This commit is contained in:
yangqiao
2024-12-30 17:47:28 +08:00
parent 8b4cc37514
commit 34e25633ba
71 changed files with 3699 additions and 0 deletions

View File

@@ -0,0 +1,60 @@
import { reactive } from "vue";
interface ViolationBOType {
[key: string]: string;
}
const Agent: ViolationBOType = reactive({
// 1
Converter_Group_Admin: "Converter: Converter_Group_Admin",
scheme_converter: "Converter: scheme_converter",
converter_critic: "Converter: converter_critic",
mergrid_ploter: "Converter: mergrid_ploter",
scheme_code_writer: "Converter: scheme_code_writer",
scheme_code_critic: "Converter: scheme_code_critic",
// 2
expriment_code_writer: "Executor: expriment_code_writer",
data_collector: "Executor: data_collector",
collector_code_writer: "Executor: collector_code_writer",
Inner_Executor_Admin: "Executor: Inner_Executor_Admin",
// Inner_Executor_Admin: "Executor: Executor_Group_Admin",
// 3
Generate_Group_Admin: "Generate: Generate_Group_Admin",
structure_scientist: "Generate: structure_scientist",
property_scientist: "Generate: property_scientist",
application_scientist: "Generate: application_scientist",
synthesis_scientist: "Generate: synthesis_scientist",
scheme_critic: "Generate: scheme_critic",
// 4
analysis_executor: "Optimize: analysis_executor",
analysis_pl_uv: "Optimize: analysis_pl_uv",
analysis_picturer: "Optimize: analysis_picturer",
Experiment_Optimizer: "Optimize: Experiment_Optimizer",
optimizer_critic: "Optimize: optimizer_critic",
Analysis_Group_Admin: "Optimize: Analysis_Group_Admin",
//
Outer_Retrieval_Admin: "Retrieval: Outer_Retrieval_Admin",
Outer_Converter_Admin: "Converter: Outer_Converter_Admin",
Outer_Executor_Admin: "Executor: Outer_Executor_Admin",
experiment_executor: "Executor: experiment_executor",
Outer_Generate_Admin: "Generate: Outer_Generate_Admin",
Outer_Analysis_Admin: "Optimize: Outer_Analysis_Admin",
vector_code_executor: "Retrieval: vector_code_executor",
graphrag_code_executor: "Retrieval: graphrag_code_executor",
web_code_executor: "Retrieval: web_code_executor",
web_summary: "Retrieval: web_summary",
// 5
Inner_Retrieval_Admin: "Retrieval: Inner_Retrieval_Admin",
// Inner_Retrieval_Admin: "Retrieval: Retrieval_Group_Admin",
vector_searcher: "Retrieval: vector_searcher",
graphrag_searcher: "Retrieval: graphrag_searcher",
web_searcher: "Retrieval: web_searcher",
Planer: "Planner",
Planner: "Planner",
})
export function getAgent(data: any) {
let rData = Object.keys(Agent).filter(k => k.toLowerCase() === data.toLowerCase())[0]
return Agent[rData] || ''
}

View File

@@ -0,0 +1,10 @@
import i18n from "../lang/index"
export const generateTitle=(title:string)=>{
//i18n.global.te('routers.' + title) 只能在ts文件中用
const hasKey = i18n.global.te('routers.' + title)
if (hasKey) {
const translatedTitle = i18n.global.t('routers.' + title)
return translatedTitle
}
return title
}

View File

@@ -0,0 +1,324 @@
import axios, {
AxiosError,
AxiosInstance,
AxiosRequestConfig,
AxiosRequestHeaders,
AxiosResponse,
InternalAxiosRequestConfig
} from 'axios'
import cloneDeep from 'lodash/cloneDeep'
import debounce from 'lodash/debounce'
import isFunction from 'lodash/isFunction'
import throttle from 'lodash/throttle'
import { stringify } from 'qs'
import { ContentTypeEnum } from '../../constants'
import { AxiosRequestConfigRetry, RequestOptions, Result } from '../../types/axios'
import { AxiosCanceler } from './AxiosCancel'
import { CreateAxiosOptions } from './AxiosTransform'
// const store = useSettingStore();
// let tokenUpdateing = false;
// // 创建一个 axios 实例
// const service = axios.create({
// timeout: 5000,
// });
// const reqLists = ref<any>([]);
/**
* Axios 模块
*/
export class VAxios {
/**
* Axios实例句柄
* @private
*/
private instance: AxiosInstance
/**
* Axios配置
* @private
*/
private readonly options: CreateAxiosOptions
constructor(options: CreateAxiosOptions) {
this.options = options
this.instance = axios.create(options)
this.setupInterceptors()
}
/**
* 创建Axios实例
* @param config
* @private
*/
private createAxios(config: CreateAxiosOptions): void {
this.instance = axios.create(config)
}
/**
* 获取数据处理类
* @private
*/
private getTransform() {
const { transform } = this.options
return transform
}
/**
* 获取Axios实例
*/
getAxios(): AxiosInstance {
return this.instance
}
/**
* 配置Axios
* @param config
*/
configAxios(config: CreateAxiosOptions) {
if (!this.instance) return
this.createAxios(config)
}
/**
* 设置公共头部信息
* @param headers
*/
setHeader(headers: Record<string, string>): void {
if (!this.instance) return
Object.assign(this.instance.defaults.headers, headers)
}
/**
* 设置拦截器
* @private
*/
private setupInterceptors() {
const transform = this.getTransform()
if (!transform) return
const {
requestInterceptors,
requestInterceptorsCatch,
responseInterceptors,
responseInterceptorsCatch
} = transform
const axiosCanceler = new AxiosCanceler()
this.instance.defaults.withCredentials = false // 解决内网多api跨越问题
// 请求拦截器
this.instance.interceptors.request.use((config: InternalAxiosRequestConfig) => {
// 如果忽略取消令牌,则不会取消重复的请求
// @ts-ignore
const { ignoreCancelToken } = config.requestOptions
const ignoreCancel = ignoreCancelToken ?? this.options.requestOptions?.ignoreCancelToken
if (!ignoreCancel) axiosCanceler.addPending(config)
if (requestInterceptors && isFunction(requestInterceptors)) {
config = requestInterceptors(config, this.options) as InternalAxiosRequestConfig
}
return config
}, undefined)
// 请求错误处理
if (requestInterceptorsCatch && isFunction(requestInterceptorsCatch)) {
this.instance.interceptors.request.use(undefined, requestInterceptorsCatch)
}
// 响应结果处理
this.instance.interceptors.response.use(async (res: AxiosResponse) => {
if (res) axiosCanceler.removePending(res.config)
if (
responseInterceptors &&
isFunction(responseInterceptors) &&
responseInterceptors(res).data.code
) {
res = responseInterceptors(res)
}
return res
}, undefined)
// 响应错误处理
if (responseInterceptorsCatch && isFunction(responseInterceptorsCatch)) {
this.instance.interceptors.response.use(undefined, (error) =>
responseInterceptorsCatch(error, this.instance)
)
}
}
/**
* 支持 FormData 请求格式
* @param config
*/
supportFormData(config: AxiosRequestConfig) {
const headers = config.headers || (this.options.headers as AxiosRequestHeaders)
const contentType = headers?.['Content-Type'] || headers?.['content-type']
if (
contentType !== ContentTypeEnum.FormURLEncoded ||
!Reflect.has(config, 'data') ||
config.method?.toUpperCase() === 'GET'
) {
return config
}
return {
...config,
data: stringify(config.data, { arrayFormat: 'brackets' })
}
}
/**
* 支持 params 序列化
* @param config
*/
supportParamsStringify(config: AxiosRequestConfig) {
const headers = config.headers || this.options.headers
const contentType = headers?.['Content-Type'] || headers?.['content-type']
if (contentType === ContentTypeEnum.FormURLEncoded || !Reflect.has(config, 'params')) {
return config
}
return {
...config,
paramsSerializer: (params: any) => stringify(params, { arrayFormat: 'brackets' })
}
}
get<T = any>(config: AxiosRequestConfig, options?: RequestOptions): Promise<T> {
return this.request({ ...config, method: 'GET' }, options)
}
post<T = any>(config: AxiosRequestConfig, options?: RequestOptions): Promise<T> {
return this.request({ ...config, method: 'POST' }, options)
}
put<T = any>(config: AxiosRequestConfig, options?: RequestOptions): Promise<T> {
return this.request({ ...config, method: 'PUT' }, options)
}
delete<T = any>(config: AxiosRequestConfig, options?: RequestOptions): Promise<T> {
return this.request({ ...config, method: 'DELETE' }, options)
}
patch<T = any>(config: AxiosRequestConfig, options?: RequestOptions): Promise<T> {
return this.request({ ...config, method: 'PATCH' }, options)
}
/**
* 上传文件封装
* @param key 文件所属的key
* @param file 文件
* @param config 请求配置
* @param options
*/
upload<T = any>(
key: string,
file: File,
config: AxiosRequestConfig,
options?: RequestOptions
): Promise<T> {
const params: FormData = config.params ?? new FormData()
params.append(key, file)
return this.request(
{
...config,
method: 'POST',
headers: {
'Content-Type': ContentTypeEnum.FormData
},
params
},
options
)
}
/**
* 请求封装
* @param config
* @param options
*/
request<T = any>(config: AxiosRequestConfigRetry, options?: RequestOptions): Promise<T> {
const { requestOptions }: any = this.options
if (requestOptions.throttle !== undefined && requestOptions.debounce !== undefined) {
throw new Error('throttle and debounce cannot be set at the same time')
}
if (requestOptions.throttle && requestOptions.throttle.delay !== 0) {
return new Promise((resolve) => {
throttle(
() => resolve(this.synthesisRequest(config, options)),
requestOptions.throttle.delay
)
})
}
if (requestOptions.debounce && requestOptions.debounce.delay !== 0) {
return new Promise((resolve) => {
debounce(
() => resolve(this.synthesisRequest(config, options)),
requestOptions.debounce.delay
)
})
}
return this.synthesisRequest(config, options)
}
/**
* 请求方法
* @private
*/
private async synthesisRequest<T = any>(
config: AxiosRequestConfigRetry,
options?: RequestOptions
): Promise<T> {
let conf: CreateAxiosOptions = cloneDeep(config)
const transform = this.getTransform()
const { requestOptions } = this.options
const opt: RequestOptions = { ...requestOptions, ...options }
const { beforeRequestHook, requestCatchHook, transformRequestHook } = transform || {}
if (beforeRequestHook && isFunction(beforeRequestHook)) {
conf = beforeRequestHook(conf, opt)
}
conf.requestOptions = opt
conf = this.supportFormData(conf)
// 支持params数组参数格式化因axios默认的toFormData即为brackets方式无需配置paramsSerializer为qs有需要可解除注释参数参考qs文档
// conf = this.supportParamsStringify(conf);
return new Promise((resolve, reject) => {
this.instance
.request<any, AxiosResponse<Result>>(!config.retryCount ? conf : config)
.then((res: AxiosResponse<Result>) => {
if (transformRequestHook && isFunction(transformRequestHook)) {
try {
const ret = transformRequestHook(res, opt)
resolve(ret)
} catch (err) {
reject(err || new Error('请求错误!'))
}
return
}
resolve(res as unknown as Promise<T>)
})
.catch((e: Error | AxiosError) => {
if (requestCatchHook && isFunction(requestCatchHook)) {
reject(requestCatchHook(e, opt))
return
}
if (axios.isAxiosError(e)) {
// 在这里重写Axios的错误信息
}
reject(e)
})
})
}
}

View File

@@ -0,0 +1,67 @@
import type { AxiosRequestConfig, Canceler } from 'axios';
import axios from 'axios';
import isFunction from 'lodash/isFunction';
// 存储请求与取消令牌的键值对列表
let pendingMap = new Map<string, Canceler>();
/**
* 获取请求Url
* @param config
*/
export const getPendingUrl = (config: AxiosRequestConfig) => [config.method, config.url].join('&');
/**
* @description 请求管理器
*/
export class AxiosCanceler {
/**
* 添加请求到列表中
* @param config
*/
addPending(config: AxiosRequestConfig) {
this.removePending(config);
const url = getPendingUrl(config);
config.cancelToken =
config.cancelToken ||
new axios.CancelToken((cancel) => {
if (!pendingMap.has(url)) {
// 如果当前没有相同请求就添加
pendingMap.set(url, cancel);
}
});
}
/**
* 移除现有的所有请求
*/
removeAllPending() {
pendingMap.forEach((cancel) => {
if (cancel && isFunction(cancel)) cancel();
});
pendingMap.clear();
}
/**
* 移除指定请求
* @param config
*/
removePending(config: AxiosRequestConfig) {
const url = getPendingUrl(config);
if (pendingMap.has(url)) {
// If there is a current request identifier in pending,
// the current request needs to be cancelled and removed
const cancel = pendingMap.get(url);
if (cancel) cancel(url);
pendingMap.delete(url);
}
}
/**
* 重置
*/
reset() {
pendingMap = new Map<string, Canceler>();
}
}

View File

@@ -0,0 +1,67 @@
import type { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios'
import { AxiosError } from 'axios'
import type { RequestOptions, Result } from '../../types/axios'
/**
* @description 创建Axios实例配置
*/
export interface CreateAxiosOptions extends AxiosRequestConfig {
/**
* 请求验证方案
*
* https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication#authentication_schemes
*/
authenticationScheme?: string
/**
* 请求数据处理
*/
transform?: AxiosTransform
/**
* 请求配置
*/
requestOptions?: RequestOptions
}
/**
* Axios请求数据处理 抽象类
*/
export abstract class AxiosTransform {
/**
* 请求前钩子
*/
beforeRequestHook?: (config: AxiosRequestConfig, options: RequestOptions) => AxiosRequestConfig
/**
* 数据处理前钩子
*/
transformRequestHook?: <T = any>(res: AxiosResponse<Result>, options: RequestOptions) => T
/**
* 请求失败钩子
*/
requestCatchHook?: <T = any>(e: Error | AxiosError, options: RequestOptions) => Promise<T>
/**
* 请求拦截器
*/
requestInterceptors?: (
config: AxiosRequestConfig,
options: CreateAxiosOptions
) => AxiosRequestConfig
/**
* 响应拦截器
*/
responseInterceptors?: (res: AxiosResponse) => AxiosResponse
/**
* 请求拦截器错误处理
*/
requestInterceptorsCatch?: (error: AxiosError) => void
/**
* 响应拦截器错误处理
*/
responseInterceptorsCatch?: (error: AxiosError, instance: AxiosInstance) => void
}

View File

@@ -0,0 +1,222 @@
// axios配置 可自行根据项目进行更改,只需更改该文件即可,其他文件可以不动
// import type { AxiosInstance } from 'axios'
import isString from 'lodash/isString'
import merge from 'lodash/merge'
// import { useRouter } from 'vue-router';
// import { UserRefresh } from '@api/userCenter';
// import { useUserStore } from '../../store'
import { VAxios } from './Axios'
import type { AxiosTransform, CreateAxiosOptions } from './AxiosTransform'
import { formatRequestDate, joinTimestamp, setObjToUrlParams } from './utils'
// 通用请求头
export enum ContentTypeEnum {
Json = 'application/json;charset=UTF-8',
FormURLEncoded = 'application/x-www-form-urlencoded;charset=UTF-8',
FormData = 'multipart/form-data;charset=UTF-8'
}
const env = import.meta.env.MODE || 'development'
// 如果是mock模式 或 没启用直连代理 就不配置host 会走本地Mock拦截 或 Vite 代理
const host =
env === 'mock' || import.meta.env.VITE_IS_REQUEST_PROXY === 'true'
? ''
: import.meta.env.VITE_API_URL
// 数据处理,方便区分多种处理方式
const transform: AxiosTransform = {
// 处理请求数据。如果数据不是预期格式,可直接抛出错误
transformRequestHook: (res, options) => {
const { isTransformResponse, isReturnNativeResponse } = options
// 如果204无内容直接返回
const method:any = res.config.method?.toLowerCase()
if (res.status === 204 && ['put', 'patch', 'delete'].includes(method)) {
return res
}
// 是否返回原生响应头 比如:需要获取响应头时使用该属性
if (isReturnNativeResponse) {
return res
}
// 不进行任何处理,直接返回
// 用于页面代码可能需要直接获取codedatamessage这些信息时开启
if (!isTransformResponse) {
return res.data
}
// 错误的时候返回
const { data } = res
if (!data) {
throw new Error('请求接口错误')
}
// 这里 code为 后台统一的字段,需要在 types.ts内修改为项目自己的接口返回格式
const { code } = data
// 这里逻辑可以根据项目进行修改
const hasSuccess = data && code === 200
if (hasSuccess) {
return data.data
}
throw new Error(`请求接口错误, 错误码: ${code}`)
},
// 请求前处理配置
beforeRequestHook: (config, options) => {
const {
apiUrl,
isJoinPrefix,
urlPrefix,
joinParamsToUrl,
formatDate,
joinTime = true
} = options
// 添加接口前缀
if (isJoinPrefix && urlPrefix && isString(urlPrefix)) {
let u = urlPrefix
config.url = `${u}${config.url}`
}
// 将baseUrl拼接
if (apiUrl && isString(apiUrl)) {
config.url = `${apiUrl}${config.url}`
}
const params = config.params || {}
const data = config.data || false
if (formatDate && data && !isString(data)) {
formatRequestDate(data)
}
if (config.method?.toUpperCase() === 'GET') {
if (!isString(params)) {
// 给 get 请求加上时间戳参数,避免从缓存中拿数据。
config.params = Object.assign(params || {}, joinTimestamp(joinTime, false))
} else {
// 兼容restful风格
config.url = `${config.url + params}${joinTimestamp(joinTime, true)}`
config.params = undefined
}
} else if (!isString(params)) {
if (formatDate) {
formatRequestDate(params)
}
if (
Reflect.has(config, 'data') &&
config.data &&
(Object.keys(config.data).length > 0 || data instanceof FormData)
) {
config.data = data
config.params = params
} else {
// 非GET请求如果没有提供data则将params视为data
config.data = params
config.params = undefined
}
if (joinParamsToUrl) {
config.url = setObjToUrlParams(config.url as string, { ...config.params, ...config.data })
}
} else {
// 兼容restful风格
config.url += params
config.params = undefined
}
return config
},
// 请求拦截器处理
requestInterceptors: (config) => {
// 请求之前处理config
// const userStore = useUserStore()
// const { token } = userStore
const token = localStorage.getItem('token')
if (token && (config as Recordable)?.requestOptions?.withToken !== false) {
;(config as Recordable).headers['x-rtt-login-token'] = token
}
return config
},
// 响应拦截器处理
responseInterceptors: (res) => {
return res
},
// 响应错误处理
responseInterceptorsCatch: (error: any, instance: any) => {
const { config } = error
if (!config || !config.requestOptions.retry) return Promise.reject(error)
config.retryCount = config.retryCount || 0
if (config.retryCount >= config.requestOptions.retry.count) return Promise.reject(error)
config.retryCount += 1
const backoff = new Promise((resolve) => {
setTimeout(() => {
resolve(config)
}, config.requestOptions.retry.delay || 1)
})
config.headers = { ...config.headers, 'Content-Type': ContentTypeEnum.Json }
return backoff.then((config) => instance.request(config))
}
}
function createAxios(opt?: Partial<CreateAxiosOptions>) {
return new VAxios(
merge(
<CreateAxiosOptions>{
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication#authentication_schemes
// 例如: authenticationScheme: 'Bearer'
authenticationScheme: '',
// 超时
timeout: 10 * 1000,
// 携带Cookie
withCredentials: true,
// 头信息
headers: {
'Content-Type': ContentTypeEnum.Json,
},
// 数据处理方式
transform,
// 配置项,下面的选项都可以在独立的接口请求中覆盖
requestOptions: {
// 接口地址
apiUrl: host,
// 是否自动添加接口前缀
isJoinPrefix: true,
// 接口前缀
// 例如: https://www.baidu.com/api
// urlPrefix: '/api'
urlPrefix: import.meta.env.VITE_API_URL_PREFIX,
// 是否返回原生响应头 比如:需要获取响应头时使用该属性
isReturnNativeResponse: false,
// 需要对返回数据进行处理
isTransformResponse: false,
// post请求的时候添加参数到url
joinParamsToUrl: false,
// 格式化提交参数时间
formatDate: true,
// 是否加入时间戳
joinTime: true,
// 是否忽略请求取消令牌
// 如果启用,则重复请求时不进行处理
// 如果禁用,则重复请求时会取消当前请求
ignoreCancelToken: true,
// 是否携带token
withToken: true,
externalUrlStatus: 0,
// 重试
retry: {
count: 3,
delay: 1000
}
}
},
opt || {}
)
)
}
export const request = createAxios()

View File

@@ -0,0 +1,57 @@
import isObject from 'lodash/isObject'
import isString from 'lodash/isString'
const DATE_TIME_FORMAT = 'YYYY-MM-DD HH:mm:ss'
export function joinTimestamp<T extends boolean>(
join: boolean,
restful: T
): T extends true ? string : object
export function joinTimestamp(join: boolean, restful = false): string | object {
if (!join) {
return restful ? '' : {}
}
const now = new Date().getTime()
if (restful) {
return `?_t=${now}`
}
return { _t: now }
}
// 格式化提交参数时间
export function formatRequestDate(params: Recordable) {
if (Object.prototype.toString.call(params) !== '[object Object]') {
return
}
for (const key in params) {
// eslint-disable-next-line no-underscore-dangle
if (params[key] && params[key]._isAMomentObject) {
params[key] = params[key].format(DATE_TIME_FORMAT)
}
if (isString(key)) {
const value = params[key]
if (value) {
try {
params[key] = isString(value) ? value.trim() : value
} catch (error: any) {
throw new Error(error)
}
}
}
if (isObject(params[key])) {
formatRequestDate(params[key])
}
}
}
// 将对象转为Url参数
export function setObjToUrlParams(baseUrl: string, obj: { [index: string]: any }): string {
let parameters = ''
for (const key in obj) {
parameters += `${key}=${encodeURIComponent(obj[key])}&`
}
parameters = parameters.replace(/&$/, '')
return /\?$/.test(baseUrl) ? baseUrl + parameters : baseUrl.replace(/\/?$/, '?') + parameters
}

View File

@@ -0,0 +1,25 @@
function useWebsocket(handleMessage: any) {
const ws = new WebSocket(import.meta.env.VITE_WB_BASE_URL)
const init = () => {
bindEvent();
}
const bindEvent = () => {
ws.addEventListener('open',handleOpen,false)
ws.addEventListener('close',handleClose,false)
ws.addEventListener('error',handleError,false)
ws.addEventListener('message',handleMessage,false)
}
const handleOpen = (e: any) => {
console.log('websocket open',e);
}
const handleClose = (e: any) => {
console.log('websocket close',e);
}
const handleError = (e: any) => {
console.log('webscoket error',e)
}
init();
return ws
}
export default useWebsocket