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

894 lines
27 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="majles-mashruh-content">
<div class="" v-if="viewMode == 'list'">
<div class="search-items firefox-scrollbar">
<div
class="search-items__item mx-3 border-bottom"
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.title_type }}</a
>
<a
@click.prevent="showtext(item._source, listAnswer, i, item)"
@auxclick.prevent.stop="
showtext(item._source, listAnswer, i, item)
"
:href="urlResolver(item._id)"
target="_blank"
class="search-items__title text__15 text__blue"
>
{{ item._source.title }}
</a>
</div>
<div class="text__15 search-items__code">
<span v-if="item._source.majles_name" style="margin-left: 10px"
><span style="color: black; font-family: sahel-semi-bold"
>مجلس :</span
>
{{ item._source.majles_name }}</span
>
<span v-if="item._source.term_number" style="margin-left: 10px"
><span style="color: black; font-family: sahel-semi-bold"
>دوره :</span
>
{{ item._source.term_number }}</span
>
<span v-if="item._source.meet_number" style="margin-left: 10px"
><span style="color: black; font-family: sahel-semi-bold"
>جلسه :</span
>
{{ item._source.meet_number }}</span
>
<span v-if="item._source.meet_date" style="margin-left: 10px"
><span style="color: black; font-family: sahel-semi-bold"
>تاریخ :</span
>
{{ item._source.meet_date }}</span
>
</div>
<div class="text__15 search-items__code">
<span v-if="item._source.talker" style="margin-left: 10px"
><span style="color: black; font-family: sahel-semi-bold"
>گوینده :</span
>
{{ item._source.talker.name }} ({{
item._source.talker.semat + " از " + item._source.talker.organ
}})
</span>
</div>
<div
v-html="highlightKey(item, 'content')"
class="search-items__detail text__15 line-clamp__2"
></div>
<div v-if="item._source.topics?.length" class="search-items__content">
<div class="text__15 line-clamp__2">
<span v-if="item._source.member_count" style="margin-left: 10px"
><span style="color: black">تعداد نمایندگان :</span>
{{ item._source.member_count }}</span
>
<span v-if="item._source.content_type" style="margin-left: 10px"
><span style="color: black">نوع محتوا :</span>
{{ item._source.content_type }}</span
>
</div>
</div>
<div v-if="item._source.tags?.length" class="search-items__content">
<div class="text__15 line-clamp__2">
<span style="margin-left: 10px">برچسب : </span>
<span class="text__dark-gray">{{ textTags(item) }} </span>
</div>
</div>
<div class="search-items__content">
<div
v-if="item._source.categories?.length"
class="text__15 line-clamp__2"
>
<span style="margin-left: 10px">دسته‌ها : </span>
<span class="text__dark-gray">{{ textCategories(item) }} </span>
</div>
</div>
<!-- <div v-if="showActionMenu" class="search-item__actions"> -->
<div class="search-item__actions">
<span class="tavasi tavasi-more-vert"></span>
<button
v-can="'favorite_create'"
@click.pevent="AddToFavorites(item, i)"
title="علاقه مندی ها"
class="btn show-detail-btn favorites"
type="button"
>
<svg
class="icon"
:class="
item._source.tbookmark == 1
? 'icon-bookmark-1'
: 'icon-bookmark-2'
"
>
<use
:xlink:href="
item._source.tbookmark == 1
? '#icon-bookmark-1'
: '#icon-bookmark-2'
"
></use>
</svg>
</button>
<!-- <button
v-can="'search_analyze'"
@click="showDetails(item)"
title="نمایش جزییات"
class="btn show-detail-btn"
type="button"
>
<span class="tavasi tavasi-eye"></span>
</button> -->
<button
v-can="'search_summary'"
@click="changeCurrent(i)"
title="مشخصات"
class="btn show-detail-btn -rotate-180"
type="button"
>
<span class="tavasi tavasi-Component-71--1"></span>
</button>
<button-component
title=" کپی لینک"
buttonText=""
class="btn show-detail-btn px-1"
@click="copyToClipboard('', urlResolver(item._id))"
>
<svg class="icon icon-copy2 fz-8">
<use xlink:href="#icon-copy2"></use>
</svg>
</button-component>
</div>
</div>
</div>
<jahat-pagination
style="font-size: 13px"
v-if="pag.total"
:paginationInfo="pag"
@page-changed="pageChanged"
@page-limit-changed="pageLimitChanged"
@sort-changed="sortChanged"
>
</jahat-pagination>
</div>
<div class="container-fluid" v-if="viewMode == 'table'">
<div class="row">
<div class="col-12 pb-3 px-0">
<my-table
:items="listAnswer"
:tableColumns="domainActiveGetter.table_columns"
:tableActions="tableActions"
:paginationInfo="pagination"
:sortingInfo="sorting"
@page-changed="pageChanged"
@page-limit-changed="pageLimitChanged"
@show-details="showDetailsHandler"
@copy-link="copyLinkHandler"
@on-linked-title-click="onOnLinkedTitleClick"
@on-add-to-favorite="onOnAddToFavorite"
:showHeaderSortButton="false"
class="my-table majles-search-table"
>
</my-table>
</div>
</div>
</div>
<!-- <SubjectModal
v-if="showModal"
:selectedItem="selectedItem"
@close-modal="closeModal"
>
</SubjectModal> -->
</div>
</template>
<script>
import favoriteApi from "~/apis/favoriteApi";
import { mapState, mapActions } from "pinia";
import idbUtil from "~/mixins/idb.js";
/**
* @vue-prop {Array} [summeryKeys=] - کلیدهای خلاصه
* @vue-prop {Object} [pagination=] - صفحه بندی
*
* @vue-data {undefined} httpService - سرویس HTTP برای درخواست‌های شبکه‌ای (ممکن است تعریف نشده باشد).
* @vue-data {Object} pag - پیکربندی صفحه‌بندی.
* @vue-data {Array} listAnswer - آرایه‌ای برای ذخیره لیست پاسخ‌ها.
* @vue-data {Array} listPage - آرایه‌ای برای ذخیره شماره صفحات.
* @vue-data {number} totalCount - تعداد کل آیتم‌ها.
* @vue-data {number} countInPage - تعداد آیتم‌ها در هر صفحه.
* @vue-data {number} maxPage - حداکثر تعداد صفحات.
* @vue-data {number} currentPage - شماره صفحه فعلی.
* @vue-data {number} beginPage - شماره صفحه شروع.
* @vue-data {number} endPage - شماره صفحه پایان.
* @vue-data {number} maxLength - حداکثر طول مجاز.
* @vue-data {string} typeCount - رشته‌ای که نوع شمارش را نشان می‌دهد.
* @vue-data {string} textSearch - متن جستجو.
* @vue-data {Object} sorting - تنظیمات مرتب‌سازی.
* @vue-data {string} sorting.sortby - فیلدی که بر اساس آن مرتب‌سازی انجام می‌شود.
* @vue-data {string|undefined} sorting.sortorder - ترتیب مرتب‌سازی (صعودی، نزولی یا هیچ).
* @vue-data {Array} [currentItem = []] - آیتم فعلی.
*
* @vue-computed {Object} [mapState.userPermisionGetter] - دریافت مجوزهای کاربر
* @vue-computed {Object} [mapState.currentUser] - کاربر فعلی
* @vue-computed {Object} [mapState.searchActiveTabGetter] - دریافت تب فعال جستجو
* @vue-computed {Boolean} [showActionMenu] - نمایش منوی اقدام
*
* @vue-event {Function} mapActions.SET_LIST_ENTITY - تنظیم لیست انتیتی
* @vue-event {Function} mapActions.SET_ITEM_ENTITY - تنظیم ایتم انتیتی
*/
export default {
name: "MajlesMashruhContent",
mixins: [idbUtil],
props: {
viewMode: {
default: "list",
},
summeryKeys: {
default() {
return [];
},
},
pagination: {
default() {
return {
pages: 0,
total: 0,
page: 1,
offset: 0,
limit: 10,
};
},
},
},
async beforeMount() {
this.httpService = new HttpService(import.meta.env.VITE_REPO_BASE_URL);
this.db = await this.getDb(this.searchActiveTabGetter.key);
this.ready = true;
},
mounted() {
window.scrollTo(0, 0);
if (this.$route.query.q) this.searchText = this.$route.query.q;
},
watch: {
pagination(newVal) {
{
this.pag = newVal;
}
},
},
data() {
return {
tableColumns: [
{ key: "title", title: "عنوان", width: "6", trancate_word: 6 },
{ key: "ts_ref", title: "مرجع تصویب", width: "2" },
{ key: "ts_date", title: "تاریخ تصویب", width: "1" },
],
tableActions: [
// {
// showOutside: false,
// show: true,
// icon: "default",
// title: "علاقه مندی ها",
// to: { name: "undefined" },
// selected: false,
// disabled: false,
// howToOpen: "",
// href: "",
// class: "edit-btn",
// action: "on-add-to-favorite",
// can: "",
// },
{
showOutside: true,
show: true,
icon: "tavasi tavasi-Component-71--1",
title: "جزییات",
to: { name: "undefined" },
selected: false,
disabled: false,
howToOpen: "",
href: "",
class: "btn show-detail-btn -rotate-180",
action: "showDetails",
can: "",
},
{
showOutside: true,
show: true,
icon: "tavasi tavasi-copy2",
title: " کپی لینک",
to: { name: "undefined" },
selected: false,
disabled: false,
howToOpen: "",
href: "",
class: "show-detail-btn -rotate-180",
action: "copy-link",
can: "",
},
],
httpService: undefined,
pag: this.pagination,
listAnswer: [],
listPage: [],
totalCount: 0,
countInPage: 0,
maxPage: 0,
currentPage: 1,
beginPage: 1,
endPage: 1,
maxLength: 250,
typeCount: "",
textSearch: "",
sorting: {
sortby: "created",
sortorder: undefined, // asc | desc | none
},
// بلا استفاده ها
// navigationOptions: [],
// selectedItem: undefined,
// iscode: true,
// showModal: false,
// listId: undefined,
// projectId: undefined,
};
},
computed: {
...mapState(["userPermisionGetter", "currentUser", "selectedlists"]),
...mapState(useSearchStore, ["searchActiveTabGetter", "domainActiveGetter"]),
showActionMenu() {
let show = false;
if (this.userPermisionGetter?.length)
["search_analyze", "search_summary"].forEach(
(item) =>
(show =
this.currentUser.user_level > 1 ||
this.userPermisionGetter.includes(item))
);
return show;
},
},
methods: {
...mapActions("entity", ["SET_ITEM_ENTITY", "SET_LIST_ENTITY"]),
onOnLinkedTitleClick({ rowItem, tableColumn, index }) {
this.showtext(rowItem._source, this.listAnswer, index, rowItem);
},
onOnAddToFavorite({ rowItem, tableColumn, index }) {
this.AddToFavorites(rowItem, index);
},
showDetailsHandler(event) {
this.$emit("changeCurrent", this.listAnswer[event.index]);
},
copyLinkHandler(event) {
let id = this.listAnswer[event]._id;
copyToClipboard("", this.urlResolver(id));
},
/**
* اضافه کردن یک آیتم به لیست علاقه‌مندی‌ها یا حذف آن از لیست علاقه‌مندی‌ها
* @param {Object} item - آیتم مورد نظر
* @param {Number} index - اندیس آیتم در لیست
*/
AddToFavorites(item, index) {
if (item._source.tbookmark == 0) {
let url = favoriteApi.favorite.add;
url = url.replace("{{data_type}}", "bookmark");
url = url.replace("{{ref_key}}", this.searchActiveTabGetter.key);
const formData = {
ref_id: item._id,
title: item._source.title,
};
this.httpService.postRequest(url, formData).then((res) => {
this.updateListAnswer(index, "tbookmark", 1);
});
} else {
let url = favoriteApi.favorite.deleteByRefid;
url = url.replace("{{data_type}}", "bookmark");
url = url.replace("{{index_key}}", this.searchActiveTabGetter.key);
url = url.replace("{{ref_id}}", item._id);
const formData = {
ref_id: item._id,
title: item._source.title,
};
this.httpService.postRequest(url, formData).then((res) => {
this.updateListAnswer(index, "tbookmark", 0);
});
}
},
/**
* بروزرسانی مقدار یک ویژگی در آرایه‌ی لیست
* @param {Number} index - اندیس آیتم در لیست
* @param {String} key - کلید مورد نظر برای بروزرسانی
* @param {any} value - مقدار جدید برای کلید
*/
updateListAnswer(index, key, value) {
if (index in this.listAnswer) {
if (key in this.listAnswer[index]["_source"])
this.listAnswer[index]["_source"][key] = value;
}
},
/**
* تبدیل تاریخ به فرمت شمسی
* @param {String|Number} item - تاریخ
* @returns {String} - تاریخ به فرمت شمسی
*/
datefa(item) {
var m = item;
var d = new Date(m).toLocaleDateString("fa-IR");
return d;
},
/**
* استخراج و برگرداندن مقدار یک ویژگی از یک آیتم و بازگرداندن آن به عنوان نمایش برای متن برجسته
* @param {Object} item - آیتم مورد نظر
* @param {String} key - کلید مورد نظر برای استخراج مقدار
* @returns {String} - مقدار ویژگی یا متن برجسته
*/
highlightKey(item, key) {
var text = "";
if (item.highlight) {
if (item.highlight[key])
if (Array.isArray(item.highlight[key]))
text = item.highlight[key].join("... ");
else text = item.highlight[key];
}
if (text == "") {
text = item._source[key];
if (text.length > this.maxLength) text = text.substr(0, this.maxLength);
}
return text;
},
/**
* استخراج و برگرداندن متن برجسته از یک آیتم
* @param {Object} item - آیتم مورد نظر
* @returns {String} - متن برجسته
*/
highlightText(item) {
var text = "";
if (item.highlight) {
if (item.highlight.content) text = item.highlight.content.join("... ");
}
text = item._source.content;
if (text.length > this.maxLength) text = text.substr(0, this.maxLength);
return text;
},
/**
* تبدیل آی‌دی موجودیت و کلید موجودیت به آدرس مرورگر
* @param {String} _id - آی‌دی موجودیت
* @param {String} [key=""] - کلید موجودیت
* @returns {String} - آدرس مرورگر
*/
urlResolver(_id, key = "") {
if (key == "") key = this.searchActiveTabGetter.key;
const routeData = this.$router.resolve({
name: "navigationView",
params: {
id: _id,
key: key,
},
query: {},
});
return routeData.href;
},
/**
* نمایش متن مربوط به یک آیتم در یک پنجره جدید
* @param {Object} item - آیتم مورد نظر
* @param {Array} listAnswer - لیست پاسخ‌ها
* @param {Number} i - اندیس
* @param {Object} t - آیتم
*/
async showtext(_source, listAnswer, index, rowItem) {
let cloneList = structuredClone(listAnswer);
cloneList.forEach((item, index) => {
cloneList[index] = { ...item, ...item._source };
});
let cloneItem = structuredClone(rowItem);
const enableIdb = Boolean(import.meta.env.VITE_ENABLE_IDB);
if (enableIdb) {
this.addDisabled = true;
await this.addToIdb(this.searchActiveTabGetter.key, cloneItem);
this.addDisabled = false;
}
this.SET_ITEM_ENTITY(cloneItem);
this.SET_LIST_ENTITY(cloneList);
localStorage.setItem("myList", JSON.stringify(cloneList));
localStorage.setItem("myItem", JSON.stringify(cloneItem));
window.open(this.urlResolver(rowItem._id), "_blank");
},
/**
* بروزرسانی لیست پاسخ‌ها و مقادیر مرتبط
* @param {Array} list - لیست پاسخ‌ها
* @param {Number} count - تعداد
* @param {String} _typeCount - نوع تعداد
*/
setAnswer(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() {
this.listPage = [];
for (let i = this.endPage; i >= this.beginPage; i--) {
this.listPage.push(i);
}
setTimeout(() => {
this.scrollToTop();
}, 700);
},
/**
* رفتن به صفحه‌ی بعد یا قبلی
* @param {Number} item - آیتم
*/
nextPage(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);
},
changeCurrent: function (i) {
this.$emit("changeCurrent", this.listAnswer[i]);
},
setTextSearch(item, countInPage) {
this.textSearch = item;
this.countInPage = countInPage;
},
/**
* اسکرول به بالا
*/
scrollToTop() {
window.scrollTo(0, 0);
},
/**
* تبدیل آرایه‌ی دسته‌بندی‌ها به متن
* @param {Object} item - آیتم مورد نظر
* @returns {String} - متن دسته‌بندی‌ها
*/
textCategories(item) {
let text = "";
if (item._source.categories) {
if (Array.isArray(item._source.categories))
text = item._source.categories.join("، ");
else text = item._source.categories;
}
return text;
},
/**
* تبدیل آرایه‌ی برچسب‌ها به متن
* @param {Object} item - آیتم مورد نظر
* @returns {String} - متن برچسب‌ها
*/
textTags(item) {
let text = "";
if (item._source.tags) {
if (Array.isArray(item._source.tags))
text = item._source.tags.join("، ");
else text = item._source.tags;
}
return text;
},
/**
* تبدیل آرایه‌ی اجرا کنندگان به متن
* @param {Object} item - آیتم مورد نظر
* @returns {String} - متن اجرا کنندگان
*/
textExceuter(item) {
let text = "";
if (item._source.exceuter_organs)
item._source.exceuter_organs.forEach((element) => {
text += element.title + ",";
});
return text;
},
/**
* تبدیل آرایه‌ی گیرندگان به متن
* @param {Object} item - آیتم مورد نظر
* @returns {String} - متن گیرندگان
*/
textReceiver(item) {
let text = "";
if (item._source.receiver_organs)
item._source.receiver_organs.forEach((element) => {
text += element.title + ",";
});
return text;
},
/**
* تبدیل آرایه‌ی موضوعات به متن
* @param {Object} item - آیتم مورد نظر
* @returns {String} - متن موضوعات
*/
textTopics(item) {
let text = "";
item._source.topics.forEach((element) => {
text += element.title + ",";
});
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__tab-content {
margin-right: 0 !important;
position: relative;
width: 90%;
}
// .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);
// box-shadow: 0 0px 21px -6px rgba(0, 0, 0, 0.1) !important;
// border-radius: 10px;
.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;
&:hover{
font-size: 0.82rem !important;
}
}
&.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) {
}
@media only screen and (min-width: 768px) and (max-width: 900.98px) {
}
@media only screen and (min-width: 901px) and (max-width: 1049.98px) {
}
@media (min-width: 1050px) {
}
</style>