|
@@ -0,0 +1,542 @@
|
|
|
+<script setup lang="ts">
|
|
|
+import { onMounted, reactive, ref } from 'vue';
|
|
|
+import { useRouter } from 'vue-router';
|
|
|
+import { debounce } from 'lodash-es';
|
|
|
+import { localStg } from '@/utils/storage';
|
|
|
+import { fetchListApps, searchBizName, searchServiceUrl } from '@/service/api';
|
|
|
+import { useAuthStore } from '@/store/modules/auth';
|
|
|
+import { useAliasStore } from '@/store/modules/alias';
|
|
|
+import { useAntdForm } from '@/hooks/common/form';
|
|
|
+import AddModal from './modules/add-modal.vue'
|
|
|
+import { Modal } from 'ant-design-vue';
|
|
|
+import { $t } from '@/locales';
|
|
|
+const authStore = useAuthStore();
|
|
|
+const aliasStore = useAliasStore();
|
|
|
+const { resetFields } = useAntdForm();
|
|
|
+interface urlOption {
|
|
|
+ AppAlias: string;
|
|
|
+ Method: string;
|
|
|
+ Route: string;
|
|
|
+ ServiceName: string;
|
|
|
+}
|
|
|
+interface bizOption {
|
|
|
+ active: boolean;
|
|
|
+ app_alias: string;
|
|
|
+ app_name: string;
|
|
|
+ favor: boolean;
|
|
|
+ hash: string;
|
|
|
+ id: string;
|
|
|
+ name: string;
|
|
|
+ node_num: string;
|
|
|
+ service_name: string;
|
|
|
+}
|
|
|
+
|
|
|
+const openMonitor = ref(false);
|
|
|
+
|
|
|
+const router = useRouter();
|
|
|
+const queryParams = reactive({
|
|
|
+ name: ''
|
|
|
+});
|
|
|
+const selectOption = ref('1');
|
|
|
+let appList = ref<StorageType.appsItem[]>([]);
|
|
|
+const stateurl = ref('');
|
|
|
+const urlLoading = ref(false);
|
|
|
+const suppilerListQuery = reactive({
|
|
|
+ url: '',
|
|
|
+ pageIndex: 1,
|
|
|
+ pageSize: 100
|
|
|
+});
|
|
|
+let urlSuggestions = reactive<urlOption[]>([]);
|
|
|
+const bizCompleteRef = ref();
|
|
|
+const stateBiz = ref('');
|
|
|
+const bizLoading = ref(false);
|
|
|
+const bizSearchQuery = reactive({
|
|
|
+ name: stateBiz.value,
|
|
|
+ pageIndex: 1,
|
|
|
+ pageSize: 100
|
|
|
+});
|
|
|
+let bizSuggestions = reactive<bizOption[]>([]);
|
|
|
+let bizPageTotal = 0;
|
|
|
+let pageTotal = 0;
|
|
|
+let dialogFlag = ref(false)
|
|
|
+function handChange(val: any) {
|
|
|
+ if (val) {
|
|
|
+ const obj = val;
|
|
|
+ localStg.set('appsItem', obj);
|
|
|
+ aliasStore.setCurrentAlias(val.alias);
|
|
|
+
|
|
|
+ router
|
|
|
+ .push({
|
|
|
+ path: '/business-analysis/system-space/index',
|
|
|
+ query: {
|
|
|
+ id: val.id,
|
|
|
+ app_alias: val.alias,
|
|
|
+ name: val.name,
|
|
|
+ item: val,
|
|
|
+ live: val.live
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .catch(err => err);
|
|
|
+ }
|
|
|
+}
|
|
|
+function getList() {
|
|
|
+ fetchListApps({ pageIndex: 0, pageSize: 200 }).then((res: any) => {
|
|
|
+ if (res.code === 200) {
|
|
|
+ appList.value = res.data.list || [];
|
|
|
+ } else {
|
|
|
+ appList.value = [];
|
|
|
+ }
|
|
|
+ });
|
|
|
+}
|
|
|
+// url-滚到底部执行的方法
|
|
|
+async function handelScroll(e: any) {
|
|
|
+ if (Number(pageTotal) <= urlSuggestions.length) {
|
|
|
+ // 全部已经展示完了
|
|
|
+ suppilerListQuery.pageIndex = 1;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ const { scrollHeight, scrollTop, clientHeight } = e.target;
|
|
|
+ if (clientHeight + scrollTop + 2 >= scrollHeight) {
|
|
|
+ // 到底部
|
|
|
+ console.log('到底了~~~~~~');
|
|
|
+ suppilerListQuery.pageIndex += 1;
|
|
|
+ urlLoading.value = true;
|
|
|
+ const result = await searchServiceUrl(suppilerListQuery);
|
|
|
+ // 根据实际接口返回数据格式将数据插入到选项中
|
|
|
+ urlSuggestions = urlSuggestions.concat(result.data.list || []);
|
|
|
+ pageTotal = result.data.count || 0;
|
|
|
+ urlLoading.value = false;
|
|
|
+ }
|
|
|
+}
|
|
|
+// url-查询
|
|
|
+const querySearchAsync = debounce(async value => {
|
|
|
+ // 300ms 防抖延迟
|
|
|
+ suppilerListQuery.url = value && value.trim();
|
|
|
+ stateurl.value = value && value.trim();
|
|
|
+ if (stateurl.value === '') {
|
|
|
+ suppilerListQuery.pageIndex = 1;
|
|
|
+ }
|
|
|
+ urlLoading.value = true;
|
|
|
+ try {
|
|
|
+ const res = await searchServiceUrl(suppilerListQuery);
|
|
|
+ if (res && res.code === 200) {
|
|
|
+ urlSuggestions = res.data.list || [];
|
|
|
+ pageTotal = res.data.count || 0;
|
|
|
+ } else {
|
|
|
+ urlSuggestions = [];
|
|
|
+ pageTotal = 0;
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('搜索失败:', error);
|
|
|
+ } finally {
|
|
|
+ urlLoading.value = false;
|
|
|
+ }
|
|
|
+}, 100);
|
|
|
+function urlHandleFocus() {
|
|
|
+ querySearchAsync('');
|
|
|
+}
|
|
|
+// url-选中
|
|
|
+function handleSelect(item: urlOption) {
|
|
|
+ // 处理选中项)
|
|
|
+ const obj = appList.value.filter((m: any) => m.alias === item.AppAlias)[0];
|
|
|
+ localStg.set('appsItem', obj);
|
|
|
+ const rowItem = {
|
|
|
+ method: item.Method,
|
|
|
+ service_name: item.ServiceName,
|
|
|
+ kind: item.Route,
|
|
|
+ name: item.Route,
|
|
|
+ route: item.Route
|
|
|
+ };
|
|
|
+ localStg.set('row', rowItem);
|
|
|
+ router.push({
|
|
|
+ path: '/service/InterfaceDetail/index',
|
|
|
+ query: {
|
|
|
+ kind: item.Route,
|
|
|
+ method: item.Method,
|
|
|
+ name: item.Route,
|
|
|
+ service_name: item.ServiceName,
|
|
|
+ route: item.Route
|
|
|
+ }
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+// 业务查询
|
|
|
+const bizSearchAsync = debounce(async value => {
|
|
|
+ // if (!value) {
|
|
|
+ // bizSuggestions = [];
|
|
|
+ // return;
|
|
|
+ // }
|
|
|
+ bizSearchQuery.name = value && value.trim();
|
|
|
+ stateBiz.value = value && value.trim();
|
|
|
+ if (stateBiz.value === '') {
|
|
|
+ bizSearchQuery.pageIndex = 1;
|
|
|
+ }
|
|
|
+ bizLoading.value = true;
|
|
|
+
|
|
|
+ try {
|
|
|
+ const res = await searchBizName(bizSearchQuery);
|
|
|
+ if (res && res.code === 200) {
|
|
|
+ bizSuggestions = res.data.list || [];
|
|
|
+ bizPageTotal = res.data.total || 0;
|
|
|
+ } else {
|
|
|
+ bizSuggestions = [];
|
|
|
+ bizPageTotal = 0;
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('搜索请求失败', error);
|
|
|
+ } finally {
|
|
|
+ bizLoading.value = false;
|
|
|
+ }
|
|
|
+}, 10); // 300ms 防抖延迟
|
|
|
+function bizHandleFocus() {
|
|
|
+ bizSearchAsync('');
|
|
|
+}
|
|
|
+// 业务-滚到底部执行的方法
|
|
|
+async function bizHandelScroll(e: any) {
|
|
|
+ const { scrollHeight, scrollTop, clientHeight } = e.target;
|
|
|
+ if (Number(bizPageTotal) <= bizSuggestions.length) {
|
|
|
+ // 全部已经展示完了
|
|
|
+ bizSearchQuery.pageIndex = 1;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (clientHeight + scrollTop + 2 >= scrollHeight) {
|
|
|
+ // 到底部
|
|
|
+ console.log('到底了~~~~~~');
|
|
|
+ bizSearchQuery.pageIndex += 1;
|
|
|
+ bizLoading.value = true;
|
|
|
+ const result = await searchBizName(bizSearchQuery);
|
|
|
+ // 根据实际接口返回数据格式将数据插入到选项中
|
|
|
+ bizSuggestions = bizSuggestions.concat(result.data.list || []);
|
|
|
+ bizPageTotal = result.data.total || 0;
|
|
|
+ bizLoading.value = false;
|
|
|
+ }
|
|
|
+}
|
|
|
+// 业务-下拉选中
|
|
|
+function bizHandleSelect(item: any) {
|
|
|
+ // 处理选中项
|
|
|
+ const obj = appList.value.filter((m: any) => m.alias === item.app_alias)[0];
|
|
|
+ localStg.set('appsItem', obj);
|
|
|
+ router.push({
|
|
|
+ path: '/business-analysis/business-topics/index',
|
|
|
+ query: {
|
|
|
+ rowHash: item.hash,
|
|
|
+ rowId: item.id,
|
|
|
+ service_name: item.service_name,
|
|
|
+ name: item.name,
|
|
|
+ subconditionValue: item.name
|
|
|
+ }
|
|
|
+ });
|
|
|
+}
|
|
|
+// 表单重置
|
|
|
+async function reset() {
|
|
|
+ await resetFields();
|
|
|
+}
|
|
|
+ /** 新增按钮操作 */
|
|
|
+function handleAdd() {
|
|
|
+ reset()
|
|
|
+ dialogFlag.value = true
|
|
|
+}
|
|
|
+function toggle() {
|
|
|
+ openMonitor.value = !openMonitor.value
|
|
|
+ // router.push({ // todo
|
|
|
+ // path: '/homeNewIndex',
|
|
|
+ // query: {
|
|
|
+ // servicesNumber: this.statusData.services
|
|
|
+ // }
|
|
|
+ // })
|
|
|
+}
|
|
|
+function logout (){
|
|
|
+ Modal.confirm({
|
|
|
+ title: $t('common.tip'),
|
|
|
+ content: $t('common.logoutConfirm'),
|
|
|
+ okText: $t('common.confirm'),
|
|
|
+ cancelText: $t('common.cancel'),
|
|
|
+ onOk: () => {
|
|
|
+ authStore.logout();
|
|
|
+ }
|
|
|
+ });
|
|
|
+}
|
|
|
+function submitted(){
|
|
|
+ dialogFlag.value = false
|
|
|
+ getList();
|
|
|
+}
|
|
|
+onMounted(() => {
|
|
|
+ getList();
|
|
|
+});
|
|
|
+</script>
|
|
|
+
|
|
|
+<template>
|
|
|
+ <div class="index-wrap">
|
|
|
+ <video
|
|
|
+ v-if="!openMonitor"
|
|
|
+ class="bg_video"
|
|
|
+ data-v-93f40d6c=""
|
|
|
+ data-v-45e53fd3=""
|
|
|
+ autoplay="true"
|
|
|
+ loop="true"
|
|
|
+ muted="true"
|
|
|
+ >
|
|
|
+ <source src="@/assets/home/home.mp4" data-v-93f40d6c="" data-v-45e53fd3="" type="video/mp4" />
|
|
|
+ </video>
|
|
|
+ <div class="index">
|
|
|
+ <div class="header">
|
|
|
+ <div class="header-right">
|
|
|
+ <AButton type="primary" size="small" style="margin-right:12px;vertical-align: middle;" round @click="handleAdd">{{ $t('common.add') }}</AButton>
|
|
|
+ <IconAntDesignSyncOutlined style="font-size:20px;vertical-align: middle;margin-right:12px;" @click="toggle"/>
|
|
|
+ <ADropdown class="avatar-container right-menu-item hover-effect" style="font-size:16px;" trigger="hover">
|
|
|
+ <div class="avatar-wrapper">
|
|
|
+ <span class="user-name">{{ authStore.userInfo.userName || localStg.get('userName') }}</span>
|
|
|
+ <IconAntDesignCaretDownOutlined />
|
|
|
+ </div>
|
|
|
+ <template #overlay>
|
|
|
+ <AMenu>
|
|
|
+ <router-link to="/profile/index">
|
|
|
+ <AMenuItem key="0">
|
|
|
+ {{ $t('common.userCenter') }}
|
|
|
+ </AMenuItem>
|
|
|
+ </router-link>
|
|
|
+ <AMenuItem key="1">
|
|
|
+ <span style="display:block;" @click="logout">{{ $t('common.logout') }}</span>
|
|
|
+ </AMenuItem>
|
|
|
+ </AMenu>
|
|
|
+ </template>
|
|
|
+ </ADropdown>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div v-if="!openMonitor" class="content">
|
|
|
+ <div class="content-form">
|
|
|
+ <div class="lg-logo">
|
|
|
+ <img src="@/assets/home/app_logo.png" class="lg-img" width="32" height="32" />
|
|
|
+ </div>
|
|
|
+ <AForm ref="queryForm" :model="queryParams" class="content-form-content">
|
|
|
+ <div class="content-form-flex">
|
|
|
+ <ASelect
|
|
|
+ v-model:value="selectOption"
|
|
|
+ placeholder="请选择"
|
|
|
+ class="content-select-left"
|
|
|
+ size="large"
|
|
|
+ :bordered="false"
|
|
|
+ >
|
|
|
+ <ASelectOption value="1">应用系统</ASelectOption>
|
|
|
+ <ASelectOption value="2">接口URL</ASelectOption>
|
|
|
+ <ASelectOption value="3">业务功能</ASelectOption>
|
|
|
+ </ASelect>
|
|
|
+ <AFormItem v-if="selectOption == '1'" label="" name="name">
|
|
|
+ <ASelect
|
|
|
+ v-model="queryParams.name"
|
|
|
+ class="content-select-right"
|
|
|
+ placeholder="请选择要访问的业务系统"
|
|
|
+ clearable
|
|
|
+ filterable
|
|
|
+ value-key="id"
|
|
|
+ size="large"
|
|
|
+ :bordered="false"
|
|
|
+ @change="handChange"
|
|
|
+ >
|
|
|
+ <ASelectOption v-for="app in appList" :key="app.id" :title="app.name" :value="app.name" />
|
|
|
+ </ASelect>
|
|
|
+ </AFormItem>
|
|
|
+ <!-- 接口URL -->
|
|
|
+ <AFormItem v-if="selectOption == '2'" label="" name="url">
|
|
|
+ <ASelect
|
|
|
+ v-model:value="stateurl"
|
|
|
+ :filter-option="false"
|
|
|
+ class="content-select-right"
|
|
|
+ placeholder="请输入url"
|
|
|
+ :bordered="false"
|
|
|
+ :show-search="true"
|
|
|
+ :loading="urlLoading"
|
|
|
+ @search="querySearchAsync"
|
|
|
+ @focus="urlHandleFocus"
|
|
|
+ @popup-scroll="handelScroll"
|
|
|
+ @select="handleSelect"
|
|
|
+ >
|
|
|
+ <ASelectOption v-for="(item,index) in urlSuggestions" :key="index + item.Route + item.Method + item.ServiceName" :value="item.Method">
|
|
|
+ <div
|
|
|
+ v-show="item.Route"
|
|
|
+ class="ob-select-box"
|
|
|
+ style="display: flex; align-items: center; justify-content: space-between"
|
|
|
+ >
|
|
|
+ <ATooltip placement="bottom" effect="dark" :content="item.Route">
|
|
|
+ <span class="ob-select-title">{{ item.Route }}</span>
|
|
|
+ </ATooltip>
|
|
|
+ <div>
|
|
|
+ <ATag size="mini" color="success" class="ob-tag-right">{{ item.Method }}</ATag>
|
|
|
+ <ATag size="mini" color="blue">{{ item.ServiceName }}</ATag>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </ASelectOption>
|
|
|
+ </ASelect>
|
|
|
+ </AFormItem>
|
|
|
+
|
|
|
+ <!-- 业务 -->
|
|
|
+ <AFormItem v-if="selectOption == '3'" label="">
|
|
|
+ <ASelect
|
|
|
+ ref="bizCompleteRef"
|
|
|
+ v-model:value="stateBiz"
|
|
|
+ :filter-option="false"
|
|
|
+ class="content-select-right"
|
|
|
+ placeholder="请输入业务"
|
|
|
+ :bordered="false"
|
|
|
+ :show-search="true"
|
|
|
+ autofocus
|
|
|
+ :loading="bizLoading"
|
|
|
+ @search="bizSearchAsync"
|
|
|
+ @focus="bizHandleFocus"
|
|
|
+ @popup-scroll="bizHandelScroll"
|
|
|
+ @select="bizHandleSelect"
|
|
|
+ >
|
|
|
+ <ASelectOption v-for="item,index in bizSuggestions" :key="index + item.app_name + item.name" :value="item.name">
|
|
|
+ <div
|
|
|
+ v-show="item.name"
|
|
|
+ class="ob-select-box"
|
|
|
+ style="display: flex; align-items: center; justify-content: space-between"
|
|
|
+ >
|
|
|
+ <ATooltip placement="bottom" effect="dark" :content="item.name">
|
|
|
+ <span ref="bussinessContent" class="ob-select-title">{{ item.name }}</span>
|
|
|
+ </ATooltip>
|
|
|
+ <div>
|
|
|
+ <ATag size="mini" color="blue">{{ item.app_name }}</ATag>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </ASelectOption>
|
|
|
+ </ASelect>
|
|
|
+ </AFormItem>
|
|
|
+ </div>
|
|
|
+ </AForm>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <!-- <Monitoring v-if="openMonitor" :services-number="servicesNumber" /> -->
|
|
|
+ </div>
|
|
|
+ <!-- 添加或修改应用配置对话框 -->
|
|
|
+ <AddModal v-model:visible="dialogFlag" @submitted="submitted"/>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+.index-wrap {
|
|
|
+ // min-width: 1250px;
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ // min-height: 600px;
|
|
|
+ min-height: 100vh;
|
|
|
+ font-family: Arial, sans-serif;
|
|
|
+ // background: #fff;
|
|
|
+ position: relative;
|
|
|
+ .index {
|
|
|
+ position: relative;
|
|
|
+ padding-bottom: 0;
|
|
|
+ height: 100%;
|
|
|
+ min-height: 600px;
|
|
|
+ text-align: center;
|
|
|
+ }
|
|
|
+ .header {
|
|
|
+ position: absolute;
|
|
|
+ z-index: 99;
|
|
|
+ min-width: 1000px;
|
|
|
+ width: 100%;
|
|
|
+ border-bottom: 0;
|
|
|
+ height: 60px;
|
|
|
+ line-height: 60px;
|
|
|
+ // background: #fff;
|
|
|
+ left: 0px;
|
|
|
+ .header-right {
|
|
|
+ position: absolute;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ right: 0;
|
|
|
+ top: 0;
|
|
|
+ z-index: 100;
|
|
|
+ height: 60px;
|
|
|
+ padding-right: 24px;
|
|
|
+ padding-left: 200px;
|
|
|
+ cursor: pointer;
|
|
|
+ -webkit-tap-highlight-color: transparent;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .content {
|
|
|
+ position: absolute;
|
|
|
+ top: 50%;
|
|
|
+ left: 50%;
|
|
|
+ transform: translate(-50%, -50%);
|
|
|
+ width: 1000px;
|
|
|
+ margin: 0 auto;
|
|
|
+ .content-form {
|
|
|
+ margin-top: 20px;
|
|
|
+ width: 850px;
|
|
|
+ height: 100%;
|
|
|
+ margin: 0 auto;
|
|
|
+ text-align: left;
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+ align-items: center;
|
|
|
+ margin-bottom: 20px;
|
|
|
+ }
|
|
|
+ .content-form-content {
|
|
|
+ flex: 1;
|
|
|
+ }
|
|
|
+ .content-form-flex {
|
|
|
+ width: 100%;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: flex-start;
|
|
|
+ height: 60px;
|
|
|
+ }
|
|
|
+ .content-form-flex ::v-deep .ant-select-selector {
|
|
|
+ background: white !important;
|
|
|
+ width: 100%;
|
|
|
+ }
|
|
|
+ .content-select-left ::v-deep .ant-select-selector {
|
|
|
+ width: 120px !important;
|
|
|
+ height: 44px;
|
|
|
+ border-radius: 8px 0 0 8px;
|
|
|
+ }
|
|
|
+ .content-select-right ::v-deep .ant-select-selector {
|
|
|
+ width: 100% !important;
|
|
|
+ height: 44px;
|
|
|
+ border-radius: 0 8px 8px 0;
|
|
|
+ margin-top: 24px;
|
|
|
+ }
|
|
|
+ /* 在这里添加上面的CSS规则 */
|
|
|
+ .content-select-right ::v-deep .ant-select-dropdown {
|
|
|
+ display: block !important;
|
|
|
+ }
|
|
|
+ .content-select-right ::v-deep.ant-select .ant-select-arrow {
|
|
|
+ top: 70%;
|
|
|
+ }
|
|
|
+ .content-form-flex ::v-deep .ant-form-item {
|
|
|
+ width: 100%;
|
|
|
+ }
|
|
|
+
|
|
|
+ .lg-logo {
|
|
|
+ width: 32px;
|
|
|
+ height: 32px;
|
|
|
+ margin-right: 16px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+.bg_video {
|
|
|
+ height: 100vh;
|
|
|
+ width: 100vw;
|
|
|
+ position: absolute;
|
|
|
+ top: 0;
|
|
|
+ left: 0;
|
|
|
+ -o-object-fit: cover;
|
|
|
+ object-fit: cover;
|
|
|
+}
|
|
|
+::v-deep .ob-select-box {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: space-between;
|
|
|
+}
|
|
|
+::v-deep .ob-tag-right {
|
|
|
+ margin-right: 10px;
|
|
|
+}
|
|
|
+::v-deep .ob-select-title {
|
|
|
+ overflow: hidden;
|
|
|
+ white-space: nowrap;
|
|
|
+ text-overflow: ellipsis;
|
|
|
+ display: inline-block;
|
|
|
+ max-width: 70%;
|
|
|
+}
|
|
|
+</style>
|