<template><div ref="amisRootRef" class="my-amis-scope">加载中...</div></template>
|
|
<script setup lang="ts">
|
import { MAIN_URL } from '/@/constants';
|
import router from '/@/router/index';
|
import { accessSessionKey, handleNoAuth } from '/@/utils/request';
|
// 可以不引用, 如果你不想要任何辅助类样式的话 (比如 `m-t-xs` 这种)
|
// https://aisuda.bce.baidu.com/amis/zh-CN/style/index
|
// import 'amis/sdk/helper.css';
|
import qs from 'qs';
|
import { onMounted, onUnmounted, reactive, ref, shallowRef, watch } from 'vue';
|
import { NO_AUTH_API_LIST } from '/@/api/ai/chat';
|
import { LOGIN_URL, TEL_LOGIN_URL } from '/@/api/ai/user';
|
import { Local } from '/@/utils/storage';
|
import { isSharePage } from '/@/stores/chatRoom';
|
|
const amisRootRef = ref<HTMLDivElement>(null);
|
|
const props = defineProps({
|
schema: {
|
type: Object,
|
default: () => ({
|
type: 'page',
|
body: 'Hello World!',
|
}),
|
},
|
locals: {
|
type: Object,
|
default: () => ({}),
|
},
|
context: {
|
type: Object,
|
default: () => ({}),
|
},
|
props: {
|
type: Object,
|
default: () => ({}),
|
},
|
env: {
|
type: Object,
|
default: () => ({}),
|
},
|
});
|
|
const emit = defineEmits(['ready']);
|
function insertScript(src, callback) {
|
const script = document.createElement('script');
|
script.setAttribute('type', 'text/javascript');
|
script.setAttribute('src', src);
|
script.async = true;
|
script.onload = () => callback();
|
script.onerror = () => callback(new Error(`Failed to load ${src}`));
|
document.head.appendChild(script);
|
}
|
function loadScript(callback) {
|
if (!window.eventList.amisSdkJsPromise) {
|
window.eventList.amisSdkJsPromise = new Promise((resolve, reject) => {
|
insertScript('/static/amis/sdk/sdk.js', (error) => {
|
if (error) {
|
reject(error);
|
return;
|
}
|
resolve();
|
});
|
});
|
}
|
window.eventList.amisSdkJsPromise
|
.then(() => {
|
callback();
|
})
|
.catch((error) => {
|
callback(error);
|
});
|
}
|
|
function loadSDK() {
|
return new Promise((resolve, reject) => {
|
// loadStyles(['/static/amis/sdk/sdk.css', '/static/amis/sdk/helper.css', '/static/amis/sdk/iconfont.css']);
|
|
if (window.amisRequire) {
|
resolve();
|
return;
|
}
|
|
loadScript((err) => {
|
if (err) {
|
reject(err);
|
return;
|
}
|
resolve();
|
});
|
});
|
}
|
|
const current = router.currentRoute.value;
|
|
const location = {
|
pathname: current?.path,
|
hash: current?.hash,
|
query: current?.query,
|
search: `?${qs.stringify(current.query)}`,
|
};
|
|
const loading = ref(false);
|
const amisInstance = shallowRef(null);
|
const unmounted = ref(false);
|
|
const updateProps = () => {
|
amisInstance.value?.updateProps({
|
data: {
|
// ...props.locals,
|
},
|
context: props.context,
|
...props.props,
|
});
|
};
|
watch(
|
() => props.locals,
|
(val) => {
|
updateProps();
|
}
|
);
|
watch(
|
() => props.props,
|
(val) => {
|
updateProps();
|
}
|
);
|
|
// watch(() => router.value, (val) => {
|
|
// })
|
|
onMounted(async () => {
|
try {
|
loading.value = true;
|
await loadSDK();
|
} finally {
|
loading.value = false;
|
}
|
if (unmounted.value) {
|
return;
|
}
|
|
const scoped = amisRequire('amis/embed');
|
const { normalizeLink } = amisRequire('amis');
|
const instance = scoped.embed(
|
amisRootRef.value,
|
props.schema,
|
{
|
data: {
|
// ...props.locals,
|
},
|
context: props.context,
|
location: location,
|
|
// todo 下发 location 对象
|
...props.props,
|
},
|
{
|
requestAdaptor(api) {
|
// 支持异步,可以通过 api.mockResponse 来设置返回结果,跳过真正的请求发送
|
// 此功能自定义 fetcher 的话会失效
|
// api.context 中包含发送请求前的上下文信息
|
// 获取本地的 token
|
const accessSession = Local.get(accessSessionKey);
|
if (!NO_AUTH_API_LIST.includes(api.url) && !isSharePage.value) {
|
if (accessSession) {
|
// 将 token 添加到请求报文头中
|
api.headers['hswatersession'] = accessSession;
|
} else {
|
if (api.url !== LOGIN_URL && api.url !== TEL_LOGIN_URL) {
|
handleNoAuth(api.url);
|
throw '权限验证失败';
|
}
|
}
|
}
|
|
api.url = `${MAIN_URL}${api.url}`;
|
return api;
|
},
|
// 全局 api 适配器。
|
// 另外在 amis 配置项中的 api 也可以配置适配器,针对某个特定接口单独处理。
|
responseAdaptor(api, payload, query, request, response) {
|
// {
|
// "json_ok": true,
|
// "sections": [
|
// {
|
// "section_id": "knowledge_base",
|
// "section_name": "水务知识库",
|
// "section_title": "拥有水务行业相关的通用知识,包括:法律法规、设计规范、给排水相关知识等等"
|
// },
|
// {
|
// "section_id": "office_assistant",
|
// "section_name": "办公助手",
|
// "section_title": "办公助手能够辅助写会议通知、请假条、工作总结、PPT等工作。"
|
// },
|
// {
|
// "section_id": "customer_service",
|
// "section_name": "客户服务",
|
// "section_title": "针对水务企业对外客户服务相关的内容,包括:抄表、开账、收费,以及热线相关"
|
// },
|
// {
|
// "section_id": "network_operation",
|
// "section_name": "管网运行",
|
// "section_title": "针对水务企业管网运行与维护管理、水质管理等相关"
|
// },
|
// {
|
// "section_id": "waterworks_operation",
|
// "section_name": "水厂运行",
|
// "section_title": "针对水务企业水厂运日常运营管理服务,包括:水厂工艺流程、水泵运行调度"
|
// }
|
// ]
|
// }
|
return payload;
|
},
|
// 覆盖 amis env
|
// 参考 https://aisuda.bce.baidu.com/amis/zh-CN/docs/start/getting-started#sdk
|
jumpTo: (to, action) => {
|
return;
|
if (to === 'goBack') {
|
return router.go(-1);
|
}
|
|
to = normalizeLink(to, this.location);
|
|
if (action?.actionType === 'url') {
|
action.blank === false ? router.push(to) : window.open(to);
|
return;
|
}
|
|
// 主要是支持 nav 中的跳转
|
if (action && to && action.target) {
|
window.open(to, action.target);
|
return;
|
}
|
|
if (/^https?:\/\//.test(to)) {
|
window.location.replace(to);
|
} else {
|
router.push(to);
|
}
|
},
|
|
updateLocation: (location, replace) => {
|
// 禁止跳转
|
return;
|
if (location === 'goBack') {
|
return router.go(-1);
|
}
|
|
location = normalizeLink(location, this.location);
|
replace ? router.replace(location) : router.replace(location);
|
},
|
|
...props.env,
|
},
|
() => {
|
emit('ready', {
|
instance,
|
});
|
}
|
);
|
amisInstance.value = instance;
|
});
|
|
onUnmounted(() => {
|
unmounted.value = true;
|
|
amisInstance.value?.unmount();
|
});
|
</script>
|