search_ui/components/search/view/EmamainContent.vue
2025-02-01 14:36:10 +03:30

570 lines
16 KiB
Vue

<template>
<div class="emamain-content">
<div class="" v-if="listAnswer?.length">
<div class="search-items firefox-scrollbar">
<div
class="search-items__item mb-5 mt-4 me-2"
v-for="(item, i) in listAnswer"
:key="i"
>
<div class="search-items__header">
<a class="search-items__label text__13 text__dark-gray">
{{ item._source.type }}</a
>
<a
v-if="item._source.title || item._source.subtitle"
class="search-items__title text__15 text__blue"
:href="item._source.url"
@click.prevent="showtext(item._source, listAnswer, i, item._id)"
@auxclick.prevent.stop="
showtext(item._source, listAnswer, i, item._id)
"
>
{{ item._source.title ?? subtitle }}
</a>
<!-- <a
:href="item._source.url"
target="_blank"
class="search-items__title text__15 text__blue"
>
{{ item._source.title }}
</a> -->
</div>
<div class="text__15 text__dark-gray search-items__code">
<span style="margin-left: 10px"
>سایت : {{ item._source.author }}</span
>
<span style="margin-left: 10px"
>تاریخ : {{ item._source.date }}</span
>
</div>
<div
v-html="highlightText(item)"
class="search-items__detail text__15 line-clamp__2"
></div>
<div class="search-items__content">
<div v-if="item._source.tags" class="text__15 line-clamp__2">
<span style="margin-left: 10px">برچسب : </span>
<span class="text__dark-gray">{{ textTags(item) }} </span>
</div>
</div>
</div>
<!-- <div
v-if="maxPage > 0"
class="search-items__pagination"
style="font-family: Sahel"
>
<ul>
<li class="prev"><a @click="nextPage(1)">بعدی</a></li>
<li :class="{ active: maxPage === currentPage }">
<a @click="setPage(maxPage)">{{ maxPage }}</a>
</li>
<li v-if="endPage < maxPage - 1">
<a @click="setPage(-2)">...</a>
</li>
<li
v-for="(item, i) in listPage"
:key="i"
:class="{ active: item === currentPage }"
>
<a @click="setPage(item)">{{ item }}</a>
</li>
<li v-if="beginPage > 2"><a @click="setPage(-1)">...</a></li>
<li :class="{ active: 1 === currentPage }">
<a @click="setPage(1)">1</a>
</li>
<li class="next"><a @click="nextPage(-1)">قبلی</a></li>
</ul>
</div> -->
</div>
<jahat-pagination
style="font-size: 13px; border-top: 2px solid #dee2e6"
v-if="pagination.total"
:paginationInfo="pagination"
@page-changed="pageChanged"
@page-limit-changed="pageLimitChanged"
@sort-changed="sortChanged"
>
</jahat-pagination>
</div>
<no-data v-else></no-data>
</div>
</template>
<script>
import idbUtil from "~/mixins/idb.js";
/**
* @vue-prop {Object} [pagination=] - صفحه بندی
*
*
* @data {Array} listAnswer - آرایه‌ای برای ذخیره لیست پاسخ‌ها.
* @data {number} totalCount - تعداد کل آیتم‌ها.
* @data {string} typeCount - رشته‌ای که نوع شمارش را نشان می‌دهد.
* @data {number} countInPage - تعداد آیتم‌ها در هر صفحه.
* @data {number} maxPage - حداکثر تعداد صفحات.
* @data {number} currentPage - شماره صفحه فعلی.
* @data {number} beginPage - شماره صفحه شروع.
* @data {number} endPage - شماره صفحه پایان.
* @data {Array} listPage - آرایه‌ای برای ذخیره شماره صفحات.
* @data {string} textSearch - متن جستجو.
* @data {Object} pag - پیکربندی صفحه‌بندی.
* @data {Object} sorting - تنظیمات مرتب‌سازی.
* @data {string} sorting.sortby - فیلدی که بر اساس آن مرتب‌سازی انجام می‌شود.
* @data {string|undefined} sorting.sortorder - ترتیب مرتب‌سازی (صعودی، نزولی یا هیچ).
*/
export default {
name: "EmamainContent",
mixins: [idbUtil],
props: {
// summeryKeys: {
// default() {
// return [];
// },
// },
pagination: {
default() {
return {};
},
},
// listSelectedPoint: {
// default() {
// return [];
// },
// },
activeTabGetter: {
default() {
return {};
},
},
showActions: {
default: true,
},
},
async beforeMount() {
this.db = await this.getDb(this.activeTabGetter.key);
this.ready = true;
},
mounted() {
window.scrollTo(0, 0);
if (this.$route.query.q) this.searchText = this.$route.query.q;
},
data() {
return {
listAnswer: [],
totalCount: 0,
typeCount: "",
countInPage: 0,
maxPage: 0,
currentPage: 1,
beginPage: 1,
endPage: 1,
listPage: [],
textSearch: "",
pag: this.pagination,
sorting: {
sortby: "created",
sortorder: undefined, // asc | desc | none
},
// iscode: true,
};
},
methods: {
/**
* نمایش متن آیتم در یک تب جدید
* @param {Object} item - آیتم مورد نظر
* @param {Array} listAnswer - لیست پاسخ‌ها
* @param {Number} i - اندیس آیتم
* @param {String} _id - شناسه آیتم
*/
// item._source, listAnswer, i, item._id
async showtext(_source, listAnswer, rowItem, _id) {
let cloneList = structuredClone(listAnswer);
cloneList.forEach((item, index) => {
cloneList[index] = { ...item, ..._source };
});
let cloneItem = structuredClone(rowItem);
cloneItem = { ...rowItem, _id: _id };
const enableIdb = Boolean(import.meta.env.VITE_ENABLE_IDB);
if (enableIdb) {
this.addDisabled = true;
await this.addToIdb(this.activeTabGetter.key, cloneItem);
this.addDisabled = false;
}
window.open(_source.url, "_blank");
},
/**
* استخراج و بازگرداندن متن هایلایت شده از آیتم
* @param {Object} item - آیتم مورد بررسی
* @returns {String} - متن هایلایت شده
*/
highlightText(item) {
var text = "";
if (item.highlight) {
if (item.highlight.text) text = item.highlight.text.join("... ");
}
return text;
},
/**
* تبدیل تاریخ آیتم به فرمت شمسی
* @param {Object} item - آیتم مورد بررسی
* @returns {String} - تاریخ به فرمت شمسی
*/
datefa(item) {
var d = new Date(item._source.date).toLocaleDateString("fa-IR");
return d;
},
/**
* تنظیم پاسخ‌ها و محاسبه صفحه‌بندی
* @param {Array} list - لیست پاسخ‌ها
* @param {Number} count - تعداد کل آیتم‌ها
* @param {String} _typeCount - نوع تعداد (مساوی یا بیشتر از)
*/
setAnswer: function (list, count = -1, _typeCount = "") {
if (count != -1) {
this.totalCount = count;
this.typeCount = _typeCount == "eq" ? "مساوی با " : "بیشتر از ";
this.maxPage =
this.totalCount == 0
? 0
: Math.floor(this.totalCount / this.countInPage) + 1;
this.currentPage = 1;
this.beginPage = 2;
this.endPage = this.beginPage + 3;
if (this.endPage > this.maxPage - 1) {
this.endPage = this.maxPage - 1;
if (this.beginPage > 2) this.beginPage = this.beginPage - 1;
}
this.updateListPage();
}
const total = count;
const pages = Math.ceil(total / this.pag.limit);
const pagination = {
total: total,
pages: pages == 0 ? 1 : pages,
};
this.pag = { ...this.pagination, ...pagination };
this.listAnswer = list;
this.scrollToTop();
localStorage.setItem("answer", JSON.stringify(this.listAnswer));
},
/**
* به‌روزرسانی لیست صفحات
*/
updateListPage: function () {
this.listPage = [];
for (let i = this.endPage; i >= this.beginPage; i--) {
this.listPage.push(i);
}
},
/**
* تغییر به صفحه بعدی یا قبلی
* @param {Number} item - مقدار تغییر (مثبت یا منفی)
*/
nextPage: function (item) {
if (item > 0) this.setPage(this.currentPage + 1);
else this.setPage(this.currentPage - 1);
},
/**
* تنظیم صفحه فعلی و به‌روزرسانی صفحات
* @param {Number} item - شماره صفحه یا کد ویژه (برای شروع یا پایان)
*/
setPage: function (item) {
if (item == -1) {
// begin ...
item = 3;
this.beginPage = 2;
this.endPage = 5;
} else if (item == -2) {
// end ...
item = this.maxPage - 3;
this.beginPage = this.maxPage - 5;
this.endPage = this.maxPage - 1;
} else if (item == this.beginPage) {
this.beginPage--;
if (this.beginPage > 5) {
this.beginPage--;
this.endPage--;
} else {
this.beginPage = 2;
this.endPage = 5;
}
} else if (item == this.endPage) {
if (this.endPage < this.maxPage - 5) {
this.endPage++;
this.beginPage++;
} else {
this.beginPage = this.maxPage - 5;
this.endPage = this.maxPage - 1;
}
}
this.updateListPage();
this.currentPage = item;
this.$emit("changePage", item - 1);
},
/**
* تغییر آیتم فعلی و ارسال آن با استفاده از رویداد
* @param {Number} i - اندیس آیتم در لیست پاسخ‌ها
*/
changeCurrent: function (i) {
this.$emit("changeCurrent", this.listAnswer[i]);
},
/**
* تنظیم متن جستجو و تعداد آیتم‌ها در هر صفحه
* @param {String} item - متن جستجو
* @param {Number} countInPage - تعداد آیتم‌ها در هر صفحه
*/
setTextSearch(item, countInPage) {
this.textSearch = item;
this.countInPage = countInPage;
},
/**
* اسکرول کردن صفحه به بالای آن
*/
scrollToTop() {
window.scrollTo(0, 0);
},
/**
* تبدیل تگ‌های آیتم به یک رشته متن
* @param {Object} item - آیتم مورد بررسی
* @returns {String} - تگ‌های آیتم به صورت رشته‌ای از هم جدا شده با کاما
*/
textTags(item) {
let text = "";
if (Array.isArray(item._source.tags)) text = item._source.tags.join("، ");
else text = item._source.tags;
return text;
},
/**
* تغییر تعداد آیتم‌ها در هر صفحه و بازنشانی صفحه‌بندی
* @param {Object} paging - اطلاعات صفحه‌بندی
*/
pageLimitChanged(paging) {
this.resetPagination();
this.pag.limit = paging.limit;
this.$emit("changePage", this.pag);
},
/**
* تغییر صفحه و بازنشانی صفحه‌بندی
* @param {Object} paging - اطلاعات صفحه‌بندی
*/
pageChanged(paging) {
let page = paging.pageNumber;
page -= 1;
this.pag.offset = page * paging.limit;
this.pag.limit = paging.limit;
this.pag.page = paging.pageNumber;
this.$emit("changePage", this.pag);
},
/**
* تغییر ترتیب صفحه‌بندی و بازنشانی صفحه‌بندی
* @param {Object} sorting - اطلاعات ترتیب
*/
sortChanged(sorting) {
this.pag.page = this.pag.offset = 0;
this.sorting = sorting;
this.$emit("changePage", this.sorting);
},
/**
* بازنشانی صفحه‌بندی به مقادیر اولیه
*/
resetPagination() {
this.pag = {
pages: 0,
total: 0,
page: 1,
offset: 0,
limit: 10,
};
},
/**
* دریافت لیست آیتم‌ها بر اساس نوع موجودیت
* @param {String} _entityType - نوع موجودیت
*/
getList(_entityType) {
if (this.fetchingData) return;
this.fetchingData = true;
this.entity_type = _entityType;
let url =
searchApi.Farhanghestan.search_normal +
`/${this.pag.offset}/${this.pag.limit}`;
this.httpService.getRequest(url).then((res) => {
this.listEntity = res.hits.hits;
const total = res.hits.total.value;
const pages = Math.ceil(total / this.pag.limit);
const pagination = {
total: total,
pages: pages == 0 ? 1 : pages,
};
this.pag = { ...this.pagination, ...pagination };
this.fetchingData = false;
});
},
},
};
</script>
<style lang="scss" scoped>
.detail-page__content {
position: initial;
margin-right: 0 !important;
}
.detail-page__content {
right: 79px !important;
}
@media screen and (min-width: 992px) {
.search-system .detail-page .detail-page__content .detail-page__tab-content {
position: initial;
margin: 0 !important;
/* margin-right: 310px; */
}
}
</style>
<style lang="scss" scoped>
// .detail-page__tab-content {
// width: 90%;
// margin-right: 0 !important;
// position: relative;
// &.serve-majles {
// width: 100%;
// }
// }
// .search-items {
// overflow-y: auto;
// height: calc(100vh - 13em);
// }
.search-items__item {
position: relative;
padding: 1em;
overflow: hidden;
&:not(:last-child) {
margin-bottom: 30px;
}
&:hover,
&.active {
background-color: var(--list-background-color);
.search-item__actions {
// width: 6.5em;
width: auto;
transition: width 0.5s;
background: #fff;
border-radius: 0 0.5em 0.5em 0;
.tavasi-more-vert {
transition: all 0.2s;
display: none;
}
}
}
}
.search-item__actions {
position: absolute;
left: 0;
width: 1.6em;
top: 1em;
// overflow: hidden;
transition: all 0.5s;
display: flex;
align-items: center;
.btn {
display: flex;
align-items: center;
justify-content: center;
padding: 0.175rem 0.35rem;
&:hover {
filter: brightness(0.7);
}
.icon-copy2 {
font-size: 0.8rem;
}
&.favorites {
color: calc(--primary-color);
.icon-bookmark-1,
.icon-bookmark-2 {
height: 1.3em;
}
}
}
}
// .detail-page__content {
// top: 35px !important;
// }
// @media only screen and (min-width: 576px) and (max-width: 767.98px) {
// .detail-page__content {
// top: 170px !important;
// }
// }
// @media (max-width: 575.98px) {
// .detail-page__content {
// top: 170px !important;
// }
// }
// @media (max-width: 575.98px) {
// }
// @media only screen and (min-width: 576px) and (max-width: 767.98px) {
// .detail-page__tab-content {
// max-width: 500px;
// }
// }
// @media only screen and (min-width: 768px) and (max-width: 900.98px) {
// .detail-page__tab-content {
// max-width: 600px;
// }
// }
// @media only screen and (min-width: 901px) and (max-width: 1049.98px) {
// .detail-page__tab-content {
// max-width: 900px;
// }
// }
// @media (min-width: 1050px) {
// }
</style>