搜索结果列表页面开发
This commit is contained in:
37
src/views/Intro/components/global-choice/SkeletonProject.vue
Normal file
37
src/views/Intro/components/global-choice/SkeletonProject.vue
Normal file
@@ -0,0 +1,37 @@
|
||||
<template>
|
||||
<div class="choice-item g-card">
|
||||
<div class="choice-item-header">
|
||||
<gc-skeleton-item style="width: 100px; height: 24px;" />
|
||||
<gc-skeleton-item style="width: 30px; height: 24px;" />
|
||||
</div>
|
||||
<div class="choice-item-content">
|
||||
<gc-skeleton-item
|
||||
style="
|
||||
width: 80px;
|
||||
height: 22px;
|
||||
border-radius: 22px;
|
||||
margin-top: 12px;
|
||||
"
|
||||
/>
|
||||
<gc-skeleton-item style="height: 14px; margin-top: 0.75rem;" />
|
||||
<gc-skeleton-item style="width: 50%; height: 14px; margin-top: 0.75rem;" />
|
||||
</div>
|
||||
<div class="choice-item-footer">
|
||||
<gc-skeleton-item style="width: 50px; height: 14px;" />
|
||||
<gc-skeleton-item style="width: 50px; height: 14px;" />
|
||||
<gc-skeleton-item style="width: 50px; height: 14px;" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.choice-item {
|
||||
@apply min-h-[200px] p-[20px];
|
||||
.choice-item-header {
|
||||
@apply flex items-center justify-between pb-[20px];
|
||||
}
|
||||
.choice-item-footer {
|
||||
@apply flex items-center gap-4 mt-3;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
284
src/views/Intro/components/global-choice/index.vue
Normal file
284
src/views/Intro/components/global-choice/index.vue
Normal file
@@ -0,0 +1,284 @@
|
||||
<script setup lang="ts">
|
||||
defineOptions({ name: 'GlobalChoice' });
|
||||
import { ref, reactive, onMounted } from 'vue';
|
||||
import { reqCatch } from '@/utils/catch';
|
||||
import { globalFeaturedGroups, globalFeaturedProjects } from '@/api/home';
|
||||
import type { projectSearchInfo } from '@/api/home/types';
|
||||
import PSkeleton from './SkeletonProject.vue';
|
||||
import LoadingMore from '@/components/LoadingMore/index.vue';
|
||||
|
||||
const loading = ref(false);
|
||||
const groupList = ref<{ id: string; name: string }[]>([]);
|
||||
const projectList = ref<projectSearchInfo[]>([]);
|
||||
const activeId = ref('');
|
||||
const pager = reactive({
|
||||
page: 1,
|
||||
pageSize: 12,
|
||||
total: 0,
|
||||
loading: false,
|
||||
error: false,
|
||||
end: false
|
||||
});
|
||||
|
||||
// 获取精选组织
|
||||
const fetchFeaturedGroups = async() => {
|
||||
loading.value = true;
|
||||
const result = await reqCatch(globalFeaturedGroups);
|
||||
loading.value = false;
|
||||
if (!result.error) {
|
||||
const data = result.data.data;
|
||||
groupList.value = data;
|
||||
}
|
||||
};
|
||||
|
||||
fetchFeaturedGroups();
|
||||
|
||||
const handleClickTag = (key: string = '') => {
|
||||
if (activeId.value === key) return;
|
||||
activeId.value = key;
|
||||
pager.page = 1;
|
||||
pager.end = false;
|
||||
fetchProjects();
|
||||
};
|
||||
|
||||
// 获取精选项目
|
||||
const fetchProjects = async() => {
|
||||
if (pager.error) pager.error = false;
|
||||
pager.loading = true;
|
||||
const result = await reqCatch(globalFeaturedProjects, {
|
||||
group_id: activeId.value,
|
||||
page: pager.page,
|
||||
per_page: pager.pageSize
|
||||
});
|
||||
pager.loading = false;
|
||||
if (!result.error) {
|
||||
const { content = [], total = 0, page_num = 0 } = result.data.data;
|
||||
pager.total = total;
|
||||
const list = content.map((item: projectSearchInfo) => {
|
||||
item.main_repository_language = item?.main_repository_language?.filter((e) => !!e) || [];
|
||||
return item;
|
||||
});
|
||||
|
||||
if (pager.page === 1) {
|
||||
projectList.value = list;
|
||||
} else {
|
||||
projectList.value = projectList.value.concat(list);
|
||||
}
|
||||
pager.end = content.length < pager.pageSize;
|
||||
} else {
|
||||
pager.error = true;
|
||||
}
|
||||
};
|
||||
|
||||
const loadNext = () => {
|
||||
pager.page++;
|
||||
fetchProjects();
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
fetchProjects();
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<ul class="global-choice g-hidden-scrollbar">
|
||||
<d-skeleton :loading="loading">
|
||||
<li :class="['choice', { active: activeId === '' }]" @click="handleClickTag('')">
|
||||
<a>全球精选</a>
|
||||
</li>
|
||||
<li
|
||||
:class="['choice', { active: activeId === item.id }]"
|
||||
v-for="item in groupList"
|
||||
:key="item.id"
|
||||
@click="handleClickTag(item.id)"
|
||||
>
|
||||
<a>{{ item.name }}</a>
|
||||
</li>
|
||||
<template #placeholder>
|
||||
<gc-skeleton-item
|
||||
v-for="i in 3"
|
||||
:key="i"
|
||||
style="width: 100px; height: 36px; border-radius: 36px; display: inline-block"
|
||||
/>
|
||||
</template>
|
||||
</d-skeleton>
|
||||
</ul>
|
||||
|
||||
<div class="global-choice-list">
|
||||
<d-skeleton :loading="pager.loading && !projectList[0]">
|
||||
<div class="global-choice-item" v-for="item in projectList" :key="item.id">
|
||||
<!-- :to="`/${item.path_with_namespace || item.namespace}`" -->
|
||||
<div class="choice-item g-card">
|
||||
<div class="choice-item-header">
|
||||
<h5>
|
||||
<GLink :href="item.web_url">{{ item.name }}</GLink>
|
||||
</h5>
|
||||
<d-popover
|
||||
content="近7天新增Star"
|
||||
:position="['top']"
|
||||
trigger="hover"
|
||||
:mouse-enter-delay="500"
|
||||
style="background-color: #fff; color: #2d2d2e"
|
||||
>
|
||||
<div class="choice-item-stat">
|
||||
<GIcon name="gt-star7day" class="stat-icon" color="var(--devui-primary, #3b82f6)"></GIcon>
|
||||
<GNumber :number="item.star_count_seven || 0" />
|
||||
</div>
|
||||
</d-popover>
|
||||
</div>
|
||||
<div class="choice-item-content">
|
||||
<!-- <div class="tags" v-if="item.topic">
|
||||
<GLink class="tag" :href="`/topic/${t.name}`" v-for="t in item.topic" :key="t.topic_id">{{
|
||||
t.name
|
||||
}}</GLink>
|
||||
</div> -->
|
||||
<p class="desc">
|
||||
<GLink :href="item.web_url">{{ item.description }}</GLink>
|
||||
</p>
|
||||
</div>
|
||||
<div class="choice-item-footer">
|
||||
<div class="extented-item lang" v-if="item.main_repository_language[0]">
|
||||
<span class="lang-color" :style="{ backgroundColor: item.main_repository_language[1] }"></span>
|
||||
<span>{{ item.main_repository_language[0] || '' }}</span>
|
||||
</div>
|
||||
<div class="extented-item">
|
||||
<GIcon name="gt-star"></GIcon>
|
||||
<GNumber :number="item.star_count || 0" />
|
||||
</div>
|
||||
<div class="extented-item" v-if="item.license">
|
||||
<GIcon name="gt-license"></GIcon>
|
||||
<span>{{ item.license }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<template #placeholder>
|
||||
<div class="global-choice-item" v-for="i in 3" :key="i">
|
||||
<PSkeleton />
|
||||
</div>
|
||||
</template>
|
||||
</d-skeleton>
|
||||
</div>
|
||||
<LoadingMore
|
||||
v-if="projectList[0]"
|
||||
:loading="pager.loading"
|
||||
:error="pager.error"
|
||||
:end="pager.end"
|
||||
@click="loadNext"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.global-choice {
|
||||
line-height: 56px;
|
||||
@apply text-center;
|
||||
.choice {
|
||||
background-color: var(--color-CG700);
|
||||
@apply cursor-pointer inline-block rounded-[20px] leading-[24px] py-2 px-4 mr-2 text-white font-bold leading-[20px];
|
||||
&:last-of-type {
|
||||
@apply mr-0;
|
||||
}
|
||||
|
||||
&.active {
|
||||
background-color: var(--devui-primary, #3b82f6);
|
||||
}
|
||||
&:not(.active):hover {
|
||||
background-color: var(--color-G900, #2d2d2e);
|
||||
}
|
||||
a {
|
||||
color: inherit;
|
||||
}
|
||||
}
|
||||
@media screen and (max-width: 576px) {
|
||||
white-space: nowrap;
|
||||
// @apply overflow-hidden;
|
||||
overflow-y: scroll;
|
||||
margin-left: -12px;
|
||||
margin-right: -12px;
|
||||
.choice:first-of-type {
|
||||
margin-left: 12px;
|
||||
}
|
||||
.choice:last-of-type {
|
||||
margin-right: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.global-choice-list {
|
||||
margin: 0 -10px;
|
||||
@apply flex flex-wrap mt-[40px];
|
||||
}
|
||||
|
||||
.global-choice-item {
|
||||
flex-basis: 33.333%;
|
||||
padding: 10px;
|
||||
@apply overflow-hidden;
|
||||
@media screen and (max-width: 768px) {
|
||||
flex-basis: 50%;
|
||||
}
|
||||
@media screen and (max-width: 576px) {
|
||||
flex-basis: 100%;
|
||||
padding: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.choice-item {
|
||||
@apply h-[200px] p-[20px] flex flex-col overflow-hidden;
|
||||
&:hover {
|
||||
box-shadow: 0px 2px 12px 0px rgba(37, 45, 59, 0.15);
|
||||
}
|
||||
|
||||
.choice-item-header {
|
||||
@apply flex items-center justify-between pb-[20px] gap-2;
|
||||
h5 {
|
||||
font-size: 20px;
|
||||
font-family: NotoSansSC, NotoSansSC;
|
||||
line-height: 30px;
|
||||
@apply font-bold overflow-hidden text-ellipsis whitespace-nowrap;
|
||||
}
|
||||
.choice-item-stat {
|
||||
font-size: 20px;
|
||||
font-family: NotoSansSC, NotoSansSC;
|
||||
font-weight: 600;
|
||||
color: var(--devui-primary, #3b82f6);
|
||||
@apply flex items-center gap-2 whitespace-nowrap;
|
||||
}
|
||||
}
|
||||
.choice-item-content {
|
||||
@apply flex-1;
|
||||
.tags {
|
||||
@apply overflow-hidden text-ellipsis whitespace-nowrap my-2;
|
||||
.tag {
|
||||
max-width: 108px;
|
||||
@apply overflow-hidden text-ellipsis;
|
||||
background-color: var(--color-CG500);
|
||||
@apply text-xs text-white inline-block px-[10px] py-[3px] leading-[16px] rounded-[22px] mr-2;
|
||||
&:last-of-type {
|
||||
@apply mr-0;
|
||||
}
|
||||
}
|
||||
}
|
||||
.desc {
|
||||
font-family: NotoSansSC, NotoSansSC;
|
||||
@apply text-G900 line-clamp-2 leading-[20px] text-sm break-words;
|
||||
}
|
||||
}
|
||||
.choice-item-footer {
|
||||
@apply text-xs leading-[16px] mt-3 text-CG600 whitespace-nowrap overflow-hidden text-ellipsis break-words;
|
||||
.extented-item {
|
||||
@apply inline-flex items-center gap-2 mr-[17px] text-ellipsis overflow-hidden;
|
||||
&:last-of-type {
|
||||
@apply mr-0;
|
||||
}
|
||||
&.lang {
|
||||
vertical-align: top;
|
||||
}
|
||||
}
|
||||
.lang-color {
|
||||
background-color: var(--color-danger);
|
||||
@apply inline-block w-[4px] h-[12px] rounded-[1px];
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
395
src/views/Intro/components/search-tool/index.vue
Normal file
395
src/views/Intro/components/search-tool/index.vue
Normal file
@@ -0,0 +1,395 @@
|
||||
<script lang="ts" setup>
|
||||
defineOptions({ name: 'SearchTool' });
|
||||
import { homeSearchProject } from '@/api/home';
|
||||
import type { projectSearchInfo } from '@/api/home/types';
|
||||
import { ref } from 'vue';
|
||||
import { useElementSize, useLocalStorage } from '@vueuse/core';
|
||||
import debounce from 'lodash/debounce';
|
||||
import { reqCatch } from '@/utils/catch';
|
||||
import { useRouter } from 'vue-router';
|
||||
const searchValue = ref('');
|
||||
const visible = ref(false);
|
||||
const inputIng = ref(false);
|
||||
const loading = ref(false);
|
||||
const refInputGroup = ref(null);
|
||||
const searchHistoryList = useLocalStorage<{ value: string; deletable?: boolean }[]>('search-history', []);
|
||||
const searchList = ref<projectSearchInfo[]>([]);
|
||||
const router = useRouter();
|
||||
const { width } = useElementSize(refInputGroup);
|
||||
|
||||
const onKeyupEnter = (e: KeyboardEvent) => {
|
||||
goSearch();
|
||||
};
|
||||
|
||||
const handleToggle = (blo: boolean) => {
|
||||
visible.value = blo;
|
||||
};
|
||||
|
||||
const onInput = debounce((str: string) => {
|
||||
if (inputIng.value) return;
|
||||
handleSearch(str);
|
||||
}, 500);
|
||||
|
||||
const handleClear = () => {
|
||||
searchValue.value = '';
|
||||
searchList.value = [];
|
||||
};
|
||||
|
||||
/**
|
||||
* 延迟获取输入值
|
||||
* 避免从中文输入时跳转
|
||||
*/
|
||||
const goSearch = (str: string | MouseEvent = '') => {
|
||||
setTimeout(() => {
|
||||
// 点击事件重置
|
||||
if (typeof str === 'object') str = '';
|
||||
str = str || searchValue.value;
|
||||
str = str.trim();
|
||||
router.push(`/search?val=${str}`);
|
||||
saveSearchKey(str);
|
||||
}, 0);
|
||||
};
|
||||
|
||||
/**
|
||||
* 保存搜索关键词,去重,去空值
|
||||
*/
|
||||
const saveSearchKey = (str: string = '') => {
|
||||
if (str && !searchHistoryList.value.some((e) => e.value === str)) {
|
||||
const list = searchHistoryList.value.slice(0);
|
||||
list.unshift({ value: str });
|
||||
list.splice(10);
|
||||
searchHistoryList.value = list;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 搜索关键词,展示命中的项目
|
||||
*/
|
||||
const handleSearch = async(str: string = '') => {
|
||||
str = str.trim();
|
||||
if (!str) {
|
||||
searchList.value = [];
|
||||
return;
|
||||
}
|
||||
const result = await reqCatch(homeSearchProject, { search: str || '' });
|
||||
if (!result.error) {
|
||||
const data = result.data.data;
|
||||
searchList.value = data;
|
||||
}
|
||||
};
|
||||
|
||||
const handleToProject = (item: projectSearchInfo) => {
|
||||
window.open(`/${item.path_with_namespace}`);
|
||||
};
|
||||
|
||||
/**
|
||||
* 禁止已聚焦时弹框变化
|
||||
*/
|
||||
const handleInputClick = (e: Event) => {
|
||||
const inputNode = document.querySelector('.search-group .search-tool input');
|
||||
if (visible.value && inputNode === document.activeElement) {
|
||||
e.stopPropagation();
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="search-group">
|
||||
<h2 class="logo"><GIcon class="logo-icon-svg" name="gt-logo" size="182px" color="#FC5533"></GIcon>开源搜索</h2>
|
||||
<!-- <h2 class="logo">开源搜索</h2> -->
|
||||
<div
|
||||
class="search-input"
|
||||
:class="{ 'is-focus': visible, 'focus-show-dropdown': searchList[0] && visible }"
|
||||
ref="refInputGroup"
|
||||
>
|
||||
<d-dropdown
|
||||
shift-offset
|
||||
:overlay-class="`search-tool-overlay ${!searchList[0] ? 'hidden' : ''}`"
|
||||
v-model="visible"
|
||||
:align="'start'"
|
||||
:position="['bottom-start']"
|
||||
:offset="[0, 0]"
|
||||
:show-animation="false"
|
||||
@toggle="handleToggle"
|
||||
>
|
||||
<d-input
|
||||
class="search-tool"
|
||||
clearable
|
||||
placeholder="请告诉我想要查找的开源项目…"
|
||||
v-model.trim="searchValue"
|
||||
size="lg"
|
||||
@keyup.enter="onKeyupEnter"
|
||||
@input="onInput"
|
||||
@clear="handleClear"
|
||||
@compositionstart="inputIng = true"
|
||||
@compositionend="inputIng = false"
|
||||
@click="handleInputClick"
|
||||
>
|
||||
<template #prefix>
|
||||
<GIcon name="gt-search" class="search-icon" />
|
||||
</template>
|
||||
<!-- <template #append><d-button class="search-btn" variant="solid" color="var(--devui-primary, #5e7ce0)" >开搜</d-button ></template> -->
|
||||
</d-input>
|
||||
<template #menu>
|
||||
<ul
|
||||
class="search-tool-items"
|
||||
:style="{
|
||||
width: width + 'px'
|
||||
}"
|
||||
v-if="searchList[0] && visible"
|
||||
>
|
||||
<li class="item" v-for="item in searchList" :key="item.id" @click="handleToProject(item)">
|
||||
<div class="option-name">{{ item.name || '-' }}</div>
|
||||
<div class="option-desc">
|
||||
{{ item.description || '暂无简介' }}
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</template>
|
||||
</d-dropdown>
|
||||
<span class="split"></span>
|
||||
<d-button class="search-btn" size="lg" @click="goSearch">开搜</d-button>
|
||||
</div>
|
||||
<div class="search-history">
|
||||
搜索历史
|
||||
<d-popover
|
||||
content="全部清空"
|
||||
:position="['top']"
|
||||
trigger="hover"
|
||||
:mouse-enter-delay="500"
|
||||
style="background-color: #fff; color: #2d2d2e"
|
||||
>
|
||||
<GIcon
|
||||
class="cursor-pointer"
|
||||
name="gt-delete"
|
||||
color="var(--color-CG600,#707A87)"
|
||||
@click="searchHistoryList = []"
|
||||
></GIcon>
|
||||
</d-popover>
|
||||
</div>
|
||||
<div class="search-history-searchList">
|
||||
<d-tag
|
||||
size="lg"
|
||||
class="history-tag"
|
||||
v-for="(item, index) in searchHistoryList"
|
||||
:key="index"
|
||||
:deletable="item.deletable"
|
||||
@click="goSearch(item.value)"
|
||||
>
|
||||
<span :title="item.value" class="tag-name">{{ item.value }}</span>
|
||||
</d-tag>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
$borderWidth: 2px;
|
||||
@mixin primary-border {
|
||||
border: $borderWidth solid var(--devui-primary, #5e7ce0);
|
||||
}
|
||||
|
||||
@mixin default-border {
|
||||
border: $borderWidth solid var(--color-CG400, #f0f2f7);
|
||||
}
|
||||
|
||||
.search-group {
|
||||
height: 540px;
|
||||
.logo {
|
||||
height: calc(50% - 44px);
|
||||
font-size: 42px;
|
||||
font-family: NotoSansSC, NotoSansSC;
|
||||
font-weight: bold;
|
||||
|
||||
padding-top: 119px;
|
||||
padding-bottom: 46px;
|
||||
@apply text-CG800 text-center flex items-center justify-center gap-x-[8px];
|
||||
|
||||
.logo-icon-svg {
|
||||
height: 42px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
&::before {
|
||||
height: 40px;
|
||||
width: 145.829596px;
|
||||
// content: '';
|
||||
// background-image: url('@/assets/imgs/logo/gitcode-logo.png');
|
||||
@apply inline-block bg-no-repeat bg-center bg-cover align-[-0.125em];
|
||||
}
|
||||
}
|
||||
|
||||
// 输入区域
|
||||
.search-input {
|
||||
@include default-border;
|
||||
border-radius: 6px; // var(--devui-border-radius, 2px);
|
||||
@apply flex mx-auto max-w-[780px];
|
||||
.devui-input {
|
||||
height: 44px;
|
||||
}
|
||||
.devui-input__inner::placeholder {
|
||||
color: var(--color-CG600);
|
||||
}
|
||||
.devui-input__wrapper {
|
||||
@apply border-0 pl-[12px] rounded-[6px];
|
||||
}
|
||||
|
||||
.devui-input__wrapper:hover {
|
||||
@apply border-0;
|
||||
}
|
||||
|
||||
.devui-input__wrapper:not(.devui-input--error):not(.devui-input--disabled):not(.devui-input--focus):hover {
|
||||
@apply border-0;
|
||||
}
|
||||
|
||||
.devui-input-slot__append {
|
||||
@apply border-0;
|
||||
}
|
||||
|
||||
// 聚焦时处理输入框样式
|
||||
&.is-focus {
|
||||
@include primary-border;
|
||||
.split {
|
||||
&:before {
|
||||
background-color: var(--devui-primary, #5e7ce0);
|
||||
}
|
||||
}
|
||||
}
|
||||
// 聚焦时有下拉框
|
||||
&.focus-show-dropdown {
|
||||
@include primary-border;
|
||||
|
||||
.devui-input__wrapper {
|
||||
@apply rounded-bl-[0] rounded-tr-[0] rounded-br-[0] border-r-0 border-b-0;
|
||||
}
|
||||
|
||||
.devui-input__wrapper.devui-input--focus {
|
||||
@apply border-b-0 rounded-bl-[0] rounded-br-[0];
|
||||
}
|
||||
|
||||
.search-btn {
|
||||
@apply border-b-0 border-l-0 rounded-br-[0];
|
||||
}
|
||||
|
||||
.split {
|
||||
&:before {
|
||||
background-color: var(--devui-primary, #5e7ce0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.search-btn {
|
||||
height: 44px;
|
||||
background-color: #fff;
|
||||
@include default-border;
|
||||
@apply text-G900 rounded-tl-[0] rounded-bl-[0] border-0 rounded-[6px];
|
||||
}
|
||||
|
||||
.split {
|
||||
@apply bg-white flex justify-center items-center;
|
||||
|
||||
&:before {
|
||||
display: block;
|
||||
content: '';
|
||||
width: 2px;
|
||||
height: 24px;
|
||||
background-color: var(--color-CG400);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.search-icon {
|
||||
color: #9fa7b3 !important;
|
||||
font-size: 18px !important;
|
||||
}
|
||||
|
||||
// 搜索历史
|
||||
.search-history {
|
||||
font-weight: 500;
|
||||
@apply text-center text-sm text-CG600 mt-8 leading-[20px] flex justify-center items-center gap-4;
|
||||
|
||||
&-searchList {
|
||||
animation: show 1s;
|
||||
@keyframes show {
|
||||
0% {
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
@apply text-center mt-[12px] text-ellipsis line-clamp-2 overflow-hidden;
|
||||
|
||||
.history-tag {
|
||||
@apply mr-2 mb-2;
|
||||
|
||||
&:last-of-type {
|
||||
@apply mb-0 mr-0;
|
||||
}
|
||||
|
||||
.devui-tag__item {
|
||||
font-size: 14px;
|
||||
font-family: NotoSansSC, NotoSansSC;
|
||||
font-weight: 500;
|
||||
background-color: var(--color-CG300, #e4e9f0);
|
||||
// padding-left: 32px;
|
||||
// padding-right: 32px;
|
||||
transition: padding ease 0.1s;
|
||||
@apply max-w-[300px] text-G900 text-sm cursor-pointer overflow-hidden text-ellipsis whitespace-nowrap;
|
||||
|
||||
&:hover {
|
||||
@apply text-CG600;
|
||||
}
|
||||
.tag-name {
|
||||
@apply text-ellipsis overflow-hidden inline-block max-w-[100%];
|
||||
}
|
||||
}
|
||||
|
||||
&.devui-tag .devui-tag__item.devui-tag--lg {
|
||||
height: 36px;
|
||||
line-height: 34px;
|
||||
@apply py-[2] px-4;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 576px) {
|
||||
height: 340px;
|
||||
.logo {
|
||||
padding-top: 30px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 搜索下拉框
|
||||
.search-tool-overlay {
|
||||
box-shadow: none;
|
||||
@include primary-border;
|
||||
transform: translateX(-$borderWidth) translateY(-$borderWidth);
|
||||
@apply border-t-0 rounded-tl-[0] rounded-tr-[0] rounded-[6px];
|
||||
}
|
||||
|
||||
.search-tool-items {
|
||||
padding-left: 12px;
|
||||
padding-right: 12px;
|
||||
height: 100%;
|
||||
max-height: 380px;
|
||||
overflow-y: auto;
|
||||
|
||||
.item {
|
||||
padding: 12px 0px;
|
||||
border-top: 1px solid var(--color-CG300, #e4e9f0);
|
||||
@apply leading-[20px] overflow-hidden text-ellipsis cursor-pointer;
|
||||
}
|
||||
|
||||
.option-name {
|
||||
font-family: NotoSansSC, NotoSansSC;
|
||||
font-weight: 500;
|
||||
@apply text-G900 overflow-hidden text-ellipsis whitespace-nowrap;
|
||||
}
|
||||
|
||||
.option-desc {
|
||||
@apply text-CG600 overflow-hidden text-ellipsis whitespace-nowrap;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
48
src/views/Intro/index.vue
Normal file
48
src/views/Intro/index.vue
Normal file
@@ -0,0 +1,48 @@
|
||||
<template>
|
||||
<div id="home-container"></div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, onBeforeMount } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
import emitter from '@/utils/eventBus';
|
||||
import microApp from '@micro-zoe/micro-app';
|
||||
|
||||
const router = useRouter();
|
||||
const toolbarContain = ref<any>(null);
|
||||
const origin = (import.meta as any).env.VITE_CHILD_HOMEWEB_HOST;
|
||||
|
||||
onMounted(() => {
|
||||
toolbarContain.value = document.getElementById('toolbarBottom');
|
||||
microApp.renderApp({
|
||||
name: 'micoro-app-homeweb-app',
|
||||
url: origin,
|
||||
container: '#home-container',
|
||||
data: {
|
||||
emitter,
|
||||
toolbarContain,
|
||||
$router: router
|
||||
},
|
||||
iframe: true,
|
||||
baseroute: '/'
|
||||
});
|
||||
});
|
||||
onBeforeMount(() => {
|
||||
microApp.unmountApp('micoro-app-homeweb-app');
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.intro-page {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.intro-page-mobile {
|
||||
:deep(.intro-banner) {
|
||||
background: url(@/assets/imgs/home/mobile-banner.png);
|
||||
background-repeat: no-repeat, no-repeat;
|
||||
background-size: contain;
|
||||
background-position: center center;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
44
src/views/Intro/types.ts
Normal file
44
src/views/Intro/types.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
|
||||
export type dynamicListRow = {
|
||||
avatar_url?: string,
|
||||
author?: string,
|
||||
remand?: string,
|
||||
time?: string
|
||||
}
|
||||
|
||||
export type activeOrganizationRow = {
|
||||
avatar_url?: string,
|
||||
name?: string,
|
||||
description?: string,
|
||||
members?: string,
|
||||
full_path?: string,
|
||||
[propName:string]: any
|
||||
}
|
||||
|
||||
export type selectedReposListRow = {
|
||||
id?: string,
|
||||
iconList?: Array<any>,
|
||||
title?: string,
|
||||
tag?: string,
|
||||
desc?: string,
|
||||
imgUrl?: string,
|
||||
path_with_namespace?: string,
|
||||
[propName: string]: any;
|
||||
}
|
||||
|
||||
export type bannerType = {
|
||||
imgUrl?: string
|
||||
link_to?: string
|
||||
}
|
||||
|
||||
export type communityType = {
|
||||
img_url?: string,
|
||||
title?: string,
|
||||
link_to?: string,
|
||||
desc?: string
|
||||
}
|
||||
|
||||
export type operationDataType = {
|
||||
img_url?: string,
|
||||
link_to?: string,
|
||||
}
|
||||
Reference in New Issue
Block a user