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

839 lines
26 KiB
Vue
Raw 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-qanon-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 v-if="!isMajlesBuild" class="search-items__label text__13 text__dark-gray">
{{ item._source.ref_key }}</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"
v-html="highlightKey(item, 'title')"
>
</a>
</div>
<div class="text__15 search-items__code">
<!-- <span v-if="!isMajlesBuild" style="margin-left: 10px"
>
<span style="color: black">سایت منبع :</span>
<a
:href="item._source.ref_url"
target="_blank"
class="text__blue"
>
{{ item._source.ref_key }}
</a>
</span> -->
<span v-if="item._source.ts_ref" style="margin-left: 10px"
><span style="color: black; font-family: sahel-semi-bold"
>مرجع تصویب :</span
>
{{ item._source.ts_ref }}</span
>
<span v-if="item._source.ref_date" style="margin-left: 10px"
><span style="color: black; font-family: sahel-semi-bold"
>تاریخ در منبع :</span
>
{{ item._source.ref_date }}</span
>
<span v-if="item._source.ts_date" style="margin-left: 10px"
><span style="color: black; font-family: sahel-semi-bold"
>تاریخ تصویب :</span
>
{{ item._source.ts_date }}</span
>
<span v-if="item._source.eb_date" style="margin-left: 10px"
><span style="color: black; font-family: sahel-semi-bold"
>تاریخ ابلاغ :</span
>
{{ item._source.eb_date }}</span
>
</div>
<div
v-html="highlightKey(item, 'content')"
class="search-items__detail text__15 line-clamp__2"
></div>
<div
v-if="item._source.exceuter_organs?.length"
class="search-items__content"
>
<div class="text__15 line-clamp__2">
<span style="margin-left: 10px">مجریان : </span>
<span class="text__dark-gray">{{ textExceuter(item) }} </span>
</div>
</div>
<div
v-if="item._source.receiver_organs?.length"
class="search-items__content"
>
<div class="text__15 line-clamp__2">
<span style="margin-left: 10px">گیرندگان : </span>
<span class="text__dark-gray">{{ textReceiver(item) }} </span>
</div>
</div>
<div class="search-items__content">
<div
v-if="item._source.tags?.length"
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"
: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 searchApis from "~/apis/searchApi";
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 {Number} [totalCount=0] - تعداد کل
* @vue-data {Number} [countInPage=0] - تعداد در صفحه
* @vue-data {Number} [maxPage=0] - حداکثر صفحه
* @vue-data {Number} [currentPage=1] - صفحه جاری
* @vue-data {Number} [beginPage=1] - صفحه شروع
* @vue-data {Number} [endPage=1] - صفحه پایان
* @vue-data {Number} [maxLength=250] - حداکثر طول
* @vue-data {String} [typeCount=""] - نوع شمارش
* @vue-data {String} [textSearch=""] - متن جستجو
* @vue-data {undefined} [httpService=undefined] - سرویس HTTP
* @vue-data {Object} [pag=] - شیء صفحه بندی
* @vue-data {Object} [sorting={sortby: "created",sortorder: undefined,}] - مرتب‌ سازی
* @vue-data {Array} [listAnswer=[]] - لیست پاسخ‌ها
* @vue-data {Array} [listPage=[]] - لیست صفحات
*
* @vue-computed {Object} [userPermisionGetter] - دریافت مجوزهای کاربر
* @vue-computed {Object} [currentUser] - کاربر فعلی
* @vue-computed {Object} [searchActiveTabGetter] - دریافت تب فعال جستجو
* @vue-computed {Boolean} [showActionMenu] - نمایش منوی اقدام
*
* @vue-event {Function} mapActions.SET_LIST_ENTITY - تنظیم لیست انتیتی
* @vue-event {Function} mapActions.SET_ITEM_ENTITY - تنظیم ایتم انتیتی
*/
export default {
name: "MajlesQanonContent",
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: 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,
totalCount: 0,
countInPage: 0,
maxPage: 0,
currentPage: 1,
beginPage: 1,
endPage: 1,
maxLength: 250,
listAnswer: [],
listPage: [],
typeCount: "",
textSearch: "",
sorting: {
sortby: "created",
sortorder: undefined, // asc | desc | none
},
//بلا استفاده ها
// selectedItem: undefined,
// navigationOptions: [],
// showModal: false,
// iscode: true,
// listId: undefined,
// projectId: undefined,
};
},
computed: {
...mapState(["userPermisionGetter", "currentUser"]),
...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);
},
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.UpdateList();
//refresh After removing or adding favorites
//this.$emit("UpdateList", item.tbookmark);
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 = {};
this.httpService.postRequest(url, formData).then((res) => {
//refresh After removing or adding favorites
//this.$emit("UpdateList", item.tbookmark);
this.updateListAnswer(index, "tbookmark", 0);
});
}
},
/**
* بروزرسانی لیست پاسخ‌ها
* @param {Number} index - اندیس
* @param {String} key - کلید
* @param {Number} 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} 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) {
const routeData = this.$router.resolve({
name: "navigationView",
params: {
id: _id,
key: this.searchActiveTabGetter.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=-1] - تعداد کل پاسخ‌ها.
* @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);
}
setTimeout(() => {
this.scrollToTop();
}, 700);
},
/**
* حرکت به صفحه بعد یا قبلی.
* @param {Number} item - جهت حرکت (-1 برای قبلی، 1 برای بعدی).
*/
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} متن دسته‌بندی‌ها.
*/
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} 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;
}
&.favorites {
color: calc(--primary-color);
.icon-bookmark-1,
.icon-bookmark-2 {
height: 1.3em;
}
}
}
}
</style>