Skip to content
This repository has been archived by the owner on Mar 9, 2024. It is now read-only.

feat(mobile): paper list page #64

Merged
merged 5 commits into from
Nov 16, 2023
Merged
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
1 change: 1 addition & 0 deletions components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ declare module 'vue' {
PaperCard: typeof import('./src/components/paper/paperCard.vue')['default']
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']
SearchOptions: typeof import('./src/components/paper/SearchOptions.vue')['default']
WordView: typeof import('./src/components/app/WordView.vue')['default']
}
export interface ComponentCustomProperties {
Expand Down
71 changes: 71 additions & 0 deletions src/components/paper/SearchOptions.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<template>
<el-checkbox v-model="modelValue.filter.onlyCanDownload" label="仅查看可下载" border @change="updateValue" />
<el-checkbox v-model="modelValue.filter.onlyFeatured" label="仅查看优秀作业" class="mt-2" border @change="updateValue" />
<el-checkbox v-model="modelValue.showAbstract" label="显示摘要" class="mt-2" border @change="updateValue" />
<el-divider content-position="left">搜索范围</el-divider>
<el-select v-model="modelValue.searchSelectValue" placeholder="搜索内容" multiple class="w-full" @change="updateValue">
<el-option v-for="item in searchSelectOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
<el-date-picker class="mt-2" v-model="modelValue.filter.timeRange" type="daterange" unlink-panels range-separator="到"
start-placeholder="最早" end-placeholder="最晚" :shortcuts="timePresets" @change="updateValue" />
</template>

<script setup lang="ts">
import { ref } from 'vue';

const props = defineProps<{
modelValue: {
filter: {
onlyCanDownload: boolean;
onlyFeatured: boolean;
timeRange: string;
}
searchSelectValue: string[];
showAbstract: false;
};
}>();
const emit = defineEmits(['update:modelValue']);

const modelValue = ref(props.modelValue);

const updateValue = () => {
emit('update:modelValue', modelValue.value);
};

const timePresets = [
{
text: '这个月',
value: () => {
const end = new Date();
const start = new Date();
start.setTime(start.getTime() - 3600 * 1000 * 24 * 30);
return [start, end];
},
}, {
text: '今年',
value: () => {
const end = new Date();
const start = new Date(new Date().getFullYear(), 0);
return [start, end];
},
}, {
text: '最近半年',
value: () => {
const end = new Date();
const start = new Date();
start.setMonth(start.getMonth() - 6);
return [start, end];
},
},
];

const searchSelectOptions = [
{
value: 'title',
label: '标题',
}, {
value: 'keywords',
label: '关键词',
},
];
</script>
2 changes: 1 addition & 1 deletion src/pages/GroupPage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@

<el-tabs type="border-card" v-model="activeTab">
<el-tab-pane label="上传" name="first">
<el-upload drag multiple>
<el-upload multiple drag >
<el-icon class="el-icon--upload"><upload-filled /></el-icon>
<div class="el-upload__text">
拖拽文件或 <em>点击这里上传</em>
Expand Down
5 changes: 3 additions & 2 deletions src/pages/account/LoginPage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,11 @@
</el-icon>
密码
</div>
<el-input type="password" v-model="form.password" show-password />
<el-input type="password" v-model="form.password" show-password
@keyup.enter="form.userId && form.password ? login() : () => { }" />
</el-form-item>
<el-form-item class="m-0">
<el-button class="submit-button ml-auto" color="#146E3C" :loading="buttonLoading" @click="login()">
<el-button class="submit-button ml-auto" color="#146E3C" :loading="buttonLoading" @click="login">
登录
</el-button>
</el-form-item>
Expand Down
183 changes: 100 additions & 83 deletions src/pages/paper/ListPage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,51 +2,74 @@
<el-backtop :right="100" :bottom="100" />

<el-row :gutter="20">
<el-col :span="6">
<el-col v-if="!isSmallScreen" :span="isSmallScreen ? 24 : 6">
<el-card>
<div class="left-box-inner">
<el-checkbox v-model="filter.onlyCanDownload" label="仅查看可下载" border />
<el-checkbox v-model="filter.onlyFeatured" label="仅查看优秀作业" class="mt-2" border />
<el-checkbox v-model="showAbstract" label="显示摘要" class="mt-2" border />
<el-divider content-position="left">搜索范围</el-divider>

<el-select v-model="searchSelectValue" placeholder="搜索内容" multiple class="w-full">
<el-option v-for="item in searchSelectOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
<el-date-picker class="mt-2" v-model="filter.timeRange" type="daterange" unlink-panels range-separator="到"
start-placeholder="最早" end-placeholder="最晚" :shortcuts="timePresets" />
<SearchOptions v-model="searchOptions" />
</div>
</el-card>
</el-col>
<el-col :span="18">
<el-input v-model="searchContent" placeholder="搜索论文" clearable class="mb-4" @change="updateUrl">
<el-col :span="isSmallScreen ? 24 : 18">
<el-input v-model="searchContent" placeholder="搜索论文" clearable class="mb-2.5" @change="updateUrl"
:suffix-icon="isSmallScreen ? Search : ''">
<template #prepend>
<el-icon>
<el-icon v-if="!isSmallScreen">
<Search />
</el-icon>
<el-button v-else @click="showSearchOptions = !showSearchOptions">
<el-icon>
<ArrowDown v-if="!showSearchOptions" />
<ArrowUp v-else />
</el-icon>
</el-button>
</template>
</el-input>
<div v-if="loading" class="infinite-list-skeleton m-0 p-0">
<el-card v-for="n in 10" :key="n" class="mb-2.5">
<el-skeleton :rows="1" animated :loading="loading" />
<Transition name="mobile-search-option-transition">
<el-card v-if="showSearchOptions" class="mb-2.5">
<SearchOptions v-model="searchOptions" />
</el-card>
</div>
<div v-else>
<TransitionGroup name="list" tag="ul" v-infinite-scroll="load" class="infinite-list list-full-screen m-0 p-0"
infinite-scroll-immediate="false">
<li v-for="(paper, index) in processedListData.slice(0, count)" :key="index">
<div class="list-full-screen-center mx-auto px-5">
<el-row :gutter="20">
<el-col :span="6">
</el-col>
<el-col :span="18">
<paperCard :paper="paper" @click="open_paper(paper)" :showAbstract="showAbstract" />
</el-col>
</el-row>
</div>
</li>
</TransitionGroup>
</div>
</Transition>
<Transition name="mobile-search-result-transition">
<div v-if="!showSearchOptions">
<div v-if="loading" class="infinite-list-skeleton m-0 p-0">
<el-card v-for="n in 10" :key="n" class="mb-2.5">
<el-skeleton :rows="1" animated :loading="loading" />
</el-card>
</div>
<div v-else>
<TransitionGroup name="list" tag="ul" v-infinite-scroll="load" class="infinite-list list-full-screen m-0 p-0"
infinite-scroll-immediate="false">
<li v-for="(paper, index) in processedListData.slice(0, count)" :key="index">
<div class="list-full-screen-center mx-auto px-5">
<el-row :gutter="20">
<el-col :span="6">
</el-col>
<el-col :span="isSmallScreen ? 24 : 18">
<paperCard :paper="paper" @click="open_paper(paper)" :showAbstract="searchOptions.showAbstract" />
</el-col>
</el-row>
</div>
</li>
<li v-if="processedListData.length === 0" class="text-center">
<div class="list-full-screen-center mx-auto px-5">
<el-row :gutter="20">
<el-col :span="6">
</el-col>
<el-col :span="isSmallScreen ? 24 : 18">
<el-text type="info">
<el-icon>
<Remove />
</el-icon>
无结果,换个搜索条件试试?
</el-text>
</el-col>
</el-row>
</div>
</li>
</TransitionGroup>
</div>
</div>
</Transition>
</el-col>
</el-row>
</template>
Expand All @@ -56,8 +79,11 @@ import { computed, onMounted, reactive, ref } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { PaperListOutput, PaperListOutputItem, isTRPCClientError, trpc } from '../../api/trpc';
import { ElMessage } from 'element-plus';
import { Search } from '@element-plus/icons-vue';
import { useFuse } from '@vueuse/integrations/useFuse';

const isSmallScreen = screen.width <= 700;

const router = useRouter();
const route = useRoute();

Expand All @@ -70,62 +96,29 @@ const open_paper = (paper: PaperListOutputItem) => {
};

const searchContent = ref(route.query.search?.toString() ?? '');
const showAbstract = ref(false);

const timePresets = [
{
text: '这个月',
value: () => {
const end = new Date();
const start = new Date();
start.setTime(start.getTime() - 3600 * 1000 * 24 * 30);
return [start, end];
},
}, {
text: '今年',
value: () => {
const end = new Date();
const start = new Date(new Date().getFullYear(), 0);
return [start, end];
},
}, {
text: '最近半年',
value: () => {
const end = new Date();
const start = new Date();
start.setMonth(start.getMonth() - 6);
return [start, end];
},
},
];
const showSearchOptions = ref(false);

const listData = ref<PaperListOutput>([]);
const loading = ref(true);

const filter = reactive({
onlyCanDownload: false,
onlyFeatured: false,
timeRange: '',
const searchOptions = reactive({
filter: {
onlyCanDownload: false,
onlyFeatured: false,
timeRange: '',
},
searchSelectValue: ['title', 'keywords'],
showAbstract: false,
});

const updateUrl = () => {
router.replace({ query: { search: searchContent.value } });
};

const searchSelectOptions = [
{
value: 'title',
label: '标题',
}, {
value: 'keywords',
label: '关键词',
},
];
const searchSelectValue = ref(['title', 'keywords']);
const fuseOptions = computed(() => {
return {
fuseOptions: {
keys: searchSelectValue.value,
keys: searchOptions.searchSelectValue,
shouldSort: true,
threshold: 0.6,
useExtendedSearch: true,
Expand All @@ -138,13 +131,13 @@ const fuse = useFuse(searchContent, listData, fuseOptions);
const processedListData = computed(() => {
return fuse.results.value.map(e => e.item)
.filter(o => {
if (filter.onlyCanDownload && !o.canDownload)
if (searchOptions.filter.onlyCanDownload && !o.canDownload)
return false;
if (filter.onlyFeatured && !o.isFeatured)
if (searchOptions.filter.onlyFeatured && !o.isFeatured)
return false;
if (filter.timeRange &&
(o.createdAt.getTime() < Date.parse(filter.timeRange[0]) ||
o.createdAt.getTime() > Date.parse(filter.timeRange[1]))
if (searchOptions.filter.timeRange &&
(o.createdAt.getTime() < Date.parse(searchOptions.filter.timeRange[0]) ||
o.createdAt.getTime() > Date.parse(searchOptions.filter.timeRange[1]))
)
return false;
return true;
Expand Down Expand Up @@ -176,7 +169,11 @@ onMounted(async () => {
}

.infinite-list {
height: calc(100vh - 95px - 65px);
@media only screen and (max-width: 700px) {
height: calc(100svh - 95px - 65px - 70px);
}

height: calc(100svh - 95px - 65px);
list-style: none;
overflow-x: hidden;
overflow-y: scroll;
Expand Down Expand Up @@ -217,4 +214,24 @@ onMounted(async () => {
.list-leave-to {
opacity: 0;
}

.mobile-search-option-transition-enter-active,
.mobile-search-option-transition-leave-active {
transition: all 0.3s ease;
}

.mobile-search-option-transition-enter-from,
.mobile-search-option-transition-leave-to {
opacity: 0;
transform: translateY(-30px);
}

.mobile-search-result-transition-enter-active {
transition: all 0.8s cubic-bezier(.63, -0.27, .14, .53);
}

.mobile-search-result-transition-enter-from,
.mobile-search-result-transition-leave-to {
opacity: 0;
}
</style>
18 changes: 16 additions & 2 deletions src/styles/element-override.scss
Original file line number Diff line number Diff line change
Expand Up @@ -81,15 +81,29 @@
.el-input-group__prepend {
border-top-left-radius: 10px !important;
border-bottom-left-radius: 10px !important;
border-width: 2px 0 2px 0;
border-left: 2px solid var(--el-border-color) !important;
}

.el-input-group--append>.el-input__wrapper {
border-top-right-radius: 0 !important;
border-bottom-right-radius: 0 !important;
}

.el-input-group__append {
border-top-right-radius: 10px !important;
border-bottom-right-radius: 10px !important;
border-right: 2px solid var(--el-border-color) !important;
}

.el-input-group__append,
.el-input-group__prepend {
border-width: 2px 0 2px 0;
border-top: 2px solid var(--el-border-color) !important;
border-bottom: 2px solid var(--el-border-color) !important;
box-sizing: border-box;
box-shadow: none !important;
}


// Select
.el-select__popper {
border-radius: $border-radius !important;
Expand Down