فلسفه اعم از همه علوم و معارف است، زيرا موضوع آن (موجود) عام ترين موضوعات و در برگيرنده همه چيزهاست. علوم كلًاّ از حيث ثبوت موضوع متوقف بر فلسفه اند، اما فلسفه در ثبوت موضوع خود بر هيچ يك از علوم مبتنى نيست
"
+ "welcomeContent": "
\n
فلسفه اعم از همه علوم و معارف است، زيرا موضوع آن (موجود) عام ترين موضوعات و در برگيرنده همه چيزهاست. علوم كلًاّ از حيث ثبوت موضوع متوقف بر فلسفه اند، اما فلسفه در ثبوت موضوع خود بر هيچ يك از علوم مبتنى نيست
\n \n اکاردیون خوشآمدگویی\n
این متن داخل اکاردیون دیفالت باز است و میتوانی محتوای خودت را اینجا اضافه کنی.
\n \n
"
}
diff --git a/app/json/tab-bar/data-entry/sampelData.json b/app/json/data-entry/sampelData.json
similarity index 100%
rename from app/json/tab-bar/data-entry/sampelData.json
rename to app/json/data-entry/sampelData.json
diff --git a/app/json/tab-bar/data-entry/sampelDataDb.json b/app/json/data-entry/sampelDataDb.json
similarity index 87%
rename from app/json/tab-bar/data-entry/sampelDataDb.json
rename to app/json/data-entry/sampelDataDb.json
index 9b7f950..ce86a56 100755
--- a/app/json/tab-bar/data-entry/sampelDataDb.json
+++ b/app/json/data-entry/sampelDataDb.json
@@ -20,26 +20,29 @@
],
"tableColumns": [
{
- "key": "branch",
- "title": "دوره",
- "isLink": true,
- "width": "18%",
- "contextmenu": true
+ "key": "previous_info.qanon_title",
+ "title": "قانون مقدم",
+ "width": "3",
+ "trancate_word": 10
},
- { "key": "title", "title": "عنوان", "width": "15%", "contextmenu": true },
- { "key": "subtitle", "title": "عنوان محتوایی", "width": "25%" },
- { "key": "meet_code", "title": "کد جلسه", "width": "12%" },
+ { "key": "previous_info.full_path", "title": "ماده مقدم", "width": "1" },
{
- "key": "begin_date",
- "title": "تاریخ",
- "isLink": true,
- "width": "12%",
- "contextmenu": true
+ "key": "next_info.qanon_title",
+ "title": "قانون موخر",
+ "width": "3",
+ "trancate_word": 10
},
- { "key": "video_count", "title": "ت فیلم", "width": "5%" },
- { "key": "photo_count", "title": "ت تصویر", "width": "5%" },
- { "key": "sound_count", "title": "ت صوت", "width": "5%" },
- { "key": "file_count", "title": "ت فایل", "width": "5%" }
+ { "key": "next_info.full_path", "title": "ماده موخر", "width": "1" },
+ {
+ "key": "subject_unity.main_type",
+ "title": "وضعیت وحدت موضوع",
+ "width": "2"
+ },
+ {
+ "key": "conflict_relation_identification.main_type",
+ "title": "تعارض",
+ "width": "2"
+ }
],
"menuItems": [
[
diff --git a/app/json/refineCodes.json b/app/json/refineCodes.json
new file mode 100644
index 0000000..e2b2104
--- /dev/null
+++ b/app/json/refineCodes.json
@@ -0,0 +1,247 @@
+[
+ {
+ "other_id": 1,
+ "title": "آب",
+ "value": 1
+ },
+ {
+ "other_id": 2,
+ "title": "آمار، برنامه و بودجه",
+ "value": 2
+ },
+ {
+ "other_id": 3,
+ "title": "آموزش عالی، پژوهش و فناوری",
+ "value": 3
+ },
+ {
+ "other_id": 4,
+ "title": "آموزش و پرورش",
+ "value": 4
+ },
+ {
+ "other_id": 5,
+ "title": "آیین دادرسی اداری",
+ "value": 5
+ },
+ {
+ "other_id": 6,
+ "title": "آیین دادرسی مدنی",
+ "value": 6
+ },
+ {
+ "other_id": 7,
+ "title": "آیین دادرسی کیفری",
+ "value": 7
+ },
+ {
+ "other_id": 8,
+ "title": "اداری و استخدامی",
+ "value": 8
+ },
+ {
+ "other_id": 9,
+ "title": "اطلاعات، امنیت و نظامی، انتظامی",
+ "value": 9
+ },
+ {
+ "other_id": 10,
+ "title": "اموال و معاملات دولتی",
+ "value": 10
+ },
+ {
+ "other_id": 11,
+ "title": "انتخابات",
+ "value": 11
+ },
+ {
+ "other_id": 12,
+ "title": "اوقاف، اماکن دینی و امور مذهبی",
+ "value": 12
+ },
+ {
+ "other_id": 13,
+ "title": "ایثارگران",
+ "value": 13
+ },
+ {
+ "other_id": 14,
+ "title": "بانکداری",
+ "value": 14
+ },
+ {
+ "other_id": 15,
+ "title": "برق و انرژیهای نو",
+ "value": 15
+ },
+ {
+ "other_id": 16,
+ "title": "بیمه",
+ "value": 16
+ },
+ {
+ "other_id": 17,
+ "title": "تأمین اجتماعی",
+ "value": 17
+ },
+ {
+ "other_id": 18,
+ "title": "تجارت",
+ "value": 18
+ },
+ {
+ "other_id": 19,
+ "title": "تشکلهای مدنی و احزاب",
+ "value": 19
+ },
+ {
+ "other_id": 20,
+ "title": "تشکیلات و امور اداری قوه قضائیه",
+ "value": 20
+ },
+ {
+ "other_id": 21,
+ "title": "تعاون",
+ "value": 21
+ },
+ {
+ "other_id": 22,
+ "title": "تعزیرات حکومتی",
+ "value": 22
+ },
+ {
+ "other_id": 23,
+ "title": "تقسیمات کشوری و مدیریت محلی",
+ "value": 23
+ },
+ {
+ "other_id": 24,
+ "title": "ثبت اسناد و املاک",
+ "value": 24
+ },
+ {
+ "other_id": 25,
+ "title": "پولی و مالی",
+ "value": 25
+ },
+ {
+ "other_id": 26,
+ "title": "حمل و نقل",
+ "value": 26
+ },
+ {
+ "other_id": 27,
+ "title": "خانواده",
+ "value": 27
+ },
+ {
+ "other_id": 28,
+ "title": "رسانه",
+ "value": 28
+ },
+ {
+ "other_id": 29,
+ "title": "سلامت",
+ "value": 29
+ },
+ {
+ "other_id": 30,
+ "title": "صنعت",
+ "value": 30
+ },
+ {
+ "other_id": 31,
+ "title": "فرهنگ و هنر",
+ "value": 31
+ },
+ {
+ "other_id": 32,
+ "title": "فناوری اطلاعات و ارتباطات",
+ "value": 32
+ },
+ {
+ "other_id": 33,
+ "title": "کار",
+ "value": 33
+ },
+ {
+ "other_id": 34,
+ "title": "کشاورزی و منابع طبیعی",
+ "value": 34
+ },
+ {
+ "other_id": 35,
+ "title": "کیفری",
+ "value": 35
+ },
+ {
+ "other_id": 36,
+ "title": "مالکیت فکری",
+ "value": 36
+ },
+ {
+ "other_id": 37,
+ "title": "مالیات",
+ "value": 37
+ },
+ {
+ "other_id": 38,
+ "title": "محاسبات عمومی",
+ "value": 38
+ },
+ {
+ "other_id": 39,
+ "title": "محیط زیست",
+ "value": 39
+ },
+ {
+ "other_id": 40,
+ "title": "مدنی و امور حسبی",
+ "value": 40
+ },
+ {
+ "other_id": 41,
+ "title": "مسکن و شهرسازی",
+ "value": 41
+ },
+ {
+ "other_id": 42,
+ "title": "مصرف",
+ "value": 42
+ },
+ {
+ "other_id": 43,
+ "title": "معدن",
+ "value": 43
+ },
+ {
+ "other_id": 44,
+ "title": "مناطق آزاد و ویژه اقتصادی",
+ "value": 44
+ },
+ {
+ "other_id": 45,
+ "title": "میراث فرهنگی و گردشگری",
+ "value": 45
+ },
+ {
+ "other_id": 46,
+ "title": "نظام قانونگذاری",
+ "value": 46
+ },
+ {
+ "other_id": 47,
+ "title": "نظامهای صنفی و حرفهای",
+ "value": 47
+ },
+ {
+ "other_id": 48,
+ "title": "نفت و گاز",
+ "value": 48
+ },
+ {
+ "other_id": 49,
+ "title": "ورزش",
+ "value": 49
+ }
+]
diff --git a/app/json/tab-bar/data-entry/dataEntry.json b/app/json/tab-bar/data-entry/dataEntry.json
index bcc6a80..81a2d54 100755
--- a/app/json/tab-bar/data-entry/dataEntry.json
+++ b/app/json/tab-bar/data-entry/dataEntry.json
@@ -4,23 +4,20 @@
"id": "MainList",
"key": "MainList",
"label": "فهرست",
- "icon": "emojione-closed-book",
- "develop": 0,
+ "icon": "i-lucide-list",
"active": true
},
{
"id": "RuleEdit",
"label": "احکام",
"key": "RuleEdit",
- "develop": 0,
- "icon": "i-mdi-library-outline"
+ "icon": "i-lucide-scroll-text"
},
{
"id": "RelationEdit",
"key": "RelationEdit",
- "icon": "emojione-orange-book",
- "develop": 0,
- "label": "روابط"
+ "label": "روابط",
+ "icon": "i-lucide-network"
}
]
}
diff --git a/app/manuals/utilities.js b/app/manuals/utilities.js
new file mode 100755
index 0000000..367df63
--- /dev/null
+++ b/app/manuals/utilities.js
@@ -0,0 +1,773 @@
+// import Vue from "vue";
+// const crypto = require("crypto");
+import exportFromJSON from "export-from-json";
+// import store from "@store/store";
+export const isLoginRemoved = () => process.env.VUE_APP_LOGIN_REMOVE == 1;
+
+// util to export to excel file using plugin
+// https://github.com/zheeeng/export-from-json
+export const convertJsonToExcelUsingPlugin = async (
+ data,
+ fileName = "download"
+) => {
+ // 'txt'(default), 'css', 'html', 'json', 'csv', 'xls', 'xml'
+ const exportType = exportFromJSON.types.xls;
+ const withBOM = true;
+
+ return await exportFromJSON({ data, fileName, exportType, withBOM });
+};
+
+// util to export to excel file manually
+export const exportJsonToExcelManually = (JSONData, FileTitle, ShowLabel) => {
+ //If JSONData is not an object then JSON.parse will parse the JSON string in an Object
+ var arrData = typeof JSONData != "object" ? JSON.parse(JSONData) : JSONData;
+ var CSV = "";
+ //This condition will generate the Label/Header
+ if (ShowLabel) {
+ var row = "";
+ //This loop will extract the label from 1st index of on array
+ for (var index in arrData[0]) {
+ //Now convert each value to string and comma-seprated
+ row += encodeURI(index) + ",";
+ }
+ row = row.slice(0, -1);
+ //append Label row with line break
+ CSV += row + "\r\n";
+ }
+ //1st loop is to extract each row
+ for (var i = 0; i < arrData.length; i++) {
+ var row = "";
+ //2nd loop will extract each column and convert it in string comma-seprated
+ for (var index in arrData[i]) {
+ row += '"' + arrData[i][index] + '",';
+ }
+ row.slice(0, row.length - 1);
+ //add a line break after each row
+ CSV += row + "\r\n";
+ }
+ if (CSV == "") {
+ alert("Invalid data");
+ return;
+ }
+ //Generate a file name
+ // application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8;
+ // text/csv;charset=utf-8;
+ // var csvContent = "data:text/csv;charset=utf-8,%EF%BB%BF" + encodeURI(csvContent);
+
+ var filename = FileTitle;
+ var blob = new Blob([CSV], {
+ type: "text/csv;charset=utf-8,BOM",
+ });
+
+ if (navigator.msSaveBlob) {
+ // IE 10+
+ navigator.msSaveBlob(blob, filename);
+ } else {
+ var link = document.createElement("a");
+ if (link.download !== undefined) {
+ // feature detection
+ // Browsers that support HTML5 download attribute
+ var url = URL.createObjectURL(blob);
+ link.setAttribute("href", url);
+ link.style = "visibility:hidden";
+ link.download = filename + ".csv";
+ document.body.appendChild(link);
+ link.click();
+ document.body.removeChild(link);
+ }
+ }
+};
+
+// util to delay promise
+export const wait = (ms) => {
+ return (x) => {
+ return new Promise((resolve) => setTimeout(() => resolve(x), ms));
+ };
+};
+// util to createObjectByNewProperties
+export const createObjectByNewProperties = (list, allowedProperties) => {
+ const properties = [];
+
+ list.forEach((item, index) => {
+ const filtered = Object.keys(item)
+ .filter((key) => allowedProperties.includes(key))
+ .reduce((obj, key) => {
+ obj[key] = item[key];
+ return obj;
+ }, {});
+
+ properties[index] = filtered;
+ });
+ return properties;
+};
+// util to convert digits to character
+export const toNumbersInCharacters = (number) => {
+ const persianNumbers = ["۱", "۲", "۳", "۴", "۵", "۶", "۷", "۸", "۹", "۰"];
+ const arabicNumbers = ["١", "٢", "٣", "٤", "٥", "٦", "٧", "٨", "٩", "٠"];
+ const englishNumbers = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "0"];
+ const persianNumbersInCharacters = [
+ "یک",
+ "دو",
+ "سه",
+ "چهار",
+ "پنج",
+ "شش",
+ "هفت",
+ "هشت",
+ "نه",
+ "صفر",
+ ];
+
+ // only replace english number with persian number character
+ return persianNumbersInCharacters[englishNumbers.indexOf(number)];
+
+ // convert all numbers to persian digits
+ // return str.split("").map(c =>
+ // persianNumbersInCharacters[englishNumbers.indexOf(c)] ||
+ // persianNumbersInCharacters[englishNumbers.indexOf(c)] || c).join("")
+};
+// util to handle if img src is not valid
+export const handleImageSrcOnError = ({ target }, isUserAvatar = true) => {
+ if (isUserAvatar) target.classList.add("human-avatar");
+ target.classList.add("error");
+};
+// util to convert date to local date and time strng;
+export const persianDateAndTime = (stringDate, local = "fa-IR") => {
+ let date = new Date(stringDate);
+ let jsonDate = {
+ weekday: {
+ long: date.toLocaleDateString(local, { weekday: "long" }),
+ short: date.toLocaleDateString(local, { weekday: "short" }),
+ narrow: date.toLocaleDateString(local, { weekday: "narrow" }),
+ },
+ era: {
+ long: date.toLocaleDateString(local, { era: "long" }),
+ short: date.toLocaleDateString(local, { era: "short" }),
+ narrow: date.toLocaleDateString(local, { era: "narrow" }),
+ },
+ timeZoneName: {
+ long: date.toLocaleDateString(local, { timeZoneName: "long" }),
+ short: date.toLocaleDateString(local, { timeZoneName: "short" }),
+ },
+ year: {
+ numeric: date.toLocaleDateString(local, { year: "numeric" }),
+ "2-digit": date.toLocaleDateString(local, { year: "2-digit" }),
+ },
+ month: {
+ numeric: date.toLocaleDateString(local, { month: "numeric" }),
+ "2-digit": date.toLocaleDateString(local, { month: "2-digit" }),
+ long: date.toLocaleDateString(local, { month: "long" }),
+ short: date.toLocaleDateString(local, { month: "short" }),
+ narrow: date.toLocaleDateString(local, { month: "narrow" }),
+ },
+ day: {
+ numeric: date.toLocaleDateString(local, { day: "numeric" }),
+ "2-digit": date.toLocaleDateString(local, { day: "2-digit" }),
+ },
+ hour: {
+ numeric: date.toLocaleTimeString(local, { hour: "numeric" }),
+ "2-digit": date.toLocaleTimeString(local, { hour: "2-digit" }),
+ },
+ minute: {
+ numeric: date.toLocaleTimeString(local, { minute: "numeric" }),
+ "2-digit": date.toLocaleTimeString(local, { minute: "2-digit" }),
+ },
+ second: {
+ numeric: date.toLocaleTimeString(local, { second: "numeric" }),
+ "2-digit": date.toLocaleTimeString(local, { second: "2-digit" }),
+ },
+ };
+ return jsonDate;
+};
+// util to format numbers to local curency
+export const formatNumber = (price = "") => {
+ return new Intl.NumberFormat("fa-IR").format(price);
+};
+
+export const isValidHttpUrl = (string) => {
+ let url;
+
+ try {
+ url = new URL(string);
+ } catch (_) {
+ return false;
+ }
+
+ return url.protocol === "http:" || url.protocol === "https:";
+};
+export const addJsCssFileToDom = (fileUrl, fileType, uuid) => {
+ let targetElement =
+ fileType == "js" ? "script" : fileType == "css" ? "link" : "none";
+ let targetAttr =
+ fileType == "js" ? "src" : fileType == "css" ? "href" : "none";
+
+ let node = document.createElement(targetElement);
+ node.setAttribute(targetAttr, fileUrl);
+ node.setAttribute("id", targetElement + "-" + uuid);
+
+ document.head.appendChild(node);
+};
+export const removeJsCssFileFromDom = (fileType, uuid) => {
+ let targetElement =
+ fileType == "js" ? "script" : fileType == "css" ? "link" : "none";
+ document.getElementById(targetElement + "-" + uuid)?.remove();
+};
+export const clearBodyClass = (className = undefined) => {
+ if (className) document.querySelector("html").replace(className, "");
+ else document.querySelector("html").removeAttribute("class");
+};
+export const redirectToExternalLink = (href, openInNewTab) => {
+ if (href) {
+ if (isValidHttpUrl(href) && openInNewTab) window.open(href, "_blank");
+ else if (isValidHttpUrl(href) && !openInNewTab) window.location.href = href;
+ else if (!isValidHttpUrl(href) && openInNewTab) {
+ if (href.includes("www.")) window.open("http://" + href, "_blank");
+ } else if (!isValidHttpUrl(href) && !openInNewTab) {
+ if (href.includes("www.")) window.location.href = "http://" + href;
+ }
+ }
+};
+export const extractAllQueryParams = (href) => {
+ return new URLSearchParams(href);
+
+ // return new Proxy(new URLSearchParams(href), {
+ // get: (searchParams, prop) => searchParams.get(prop),
+ // });
+};
+export const makeQueryParams = (url, searchParams) => {
+ var query = new URLSearchParams();
+
+ // (A) URL SEARCH PARAMS OBJECT TO QUICKLY BUILD QUERY STRING
+ Object.keys(searchParams).forEach((key) =>
+ query.append(key, searchParams[key])
+ );
+
+ // (B) CONVERT TO STRING, APPEND TO URL
+ url += "?" + query.toString();
+ return url;
+};
+
+// export const decryptData = (
+// data,
+// key = "fTjWnZr4u7x!A%D*G-KaNdRgUkXp3s6v",
+// method = "AES-256-CBC",
+// iv = "poaskq2234??@35."
+// ) => {
+// let decipher = crypto.createDecipheriv(method, key, iv);
+// let decrypted = decipher.update(data, "base64", "utf8");
+// let dd = decrypted + decipher.final("utf8");
+// return JSON.parse(dd);
+// };
+
+// util to handle response errors
+
+export const handleErrors = (error) => {
+ return new Promise((resolve, reject) => {
+ /*
+ 401: The HTTP 401 Unauthorized response status code indicates that
+ the client request has not been completed because it lacks
+ valid authentication credentials for the requested resource.
+
+ 403: The HTTP 403 Forbidden response status code indicates that
+ the server understands the request but refuses to authorize it.
+
+ 404: The HTTP 404 Not Found response status code indicates that
+ the server cannot find the requested resource
+
+ 405: The HyperText Transfer Protocol (HTTP) 405 Method Not Allowed
+ response status code indicates that the server knows the
+ request method, but the target resource doesn't support this method
+
+ 406: Not Acceptable
+ */
+ try {
+ let res = error.response;
+
+ if (res) {
+ if (res.status === 401) {
+ toast.add({
+ title: "خطا!",
+ description: res.data.message,
+ });
+
+ // router.push({ name: 'login' })
+ } else if (res.status === 403) {
+ toast.add({
+ title: "خطا!",
+ description: res.data.message,
+ });
+ } else if (res.status === 404) {
+ toast.add({
+ title: "خطا!",
+ description: res.data.message,
+ });
+
+ // router.push('/404')
+ } else if (res.status === 405) {
+ toast.add({
+ title: "خطا!",
+ description: res.data.message,
+ });
+
+ // router.push('/404')
+ } else if (res.status === 406) {
+ toast.add({
+ title: "خطا!",
+ description: res.data.message,
+ });
+
+ // router.push('/404')
+ } else if (res.status === 500) {
+ toast.add({
+ title: "خطا!",
+ description: res.data.message ?? res.data,
+ });
+ } else {
+ toast.add({
+ title: "خطا!",
+ description: res.data.message,
+ });
+ }
+
+ resolve(error.response);
+ } else {
+ let message = "خطا!!!";
+
+ // if (error) {
+ // message = error.message ?? error;
+ // }
+ // else
+ // {
+ // message = "خطا!!!"
+ // }
+
+ reject(new Error(message));
+
+ // text: error.stack,
+ toast.add({
+ title: message,
+ });
+ }
+ } catch (error) {
+ let message = "خطا!!!";
+ message = error?.message ?? message;
+
+ return reject(new Error(message));
+ }
+ });
+};
+
+function countDownTimer(timeInSecond = 120) {
+ var timeleft = timeInSecond;
+ var downloadTimer = setInterval(function () {
+ if (timeleft <= 0) {
+ clearInterval(downloadTimer);
+ // document.getElementById("countdown").innerHTML = "Finished";
+ } else {
+ // document.getElementById("countdown").innerHTML =
+ // timeleft + " seconds remaining";
+ }
+ timeleft -= 1;
+ }, 1000);
+
+ return timeleft;
+}
+
+///////////////////////////////////////
+///// html functions
+///////////////////////////////////////
+export function getSelectionHtmlRange() {
+ var sel;
+ if (window.getSelection) {
+ sel = window.getSelection();
+ if (sel.rangeCount) {
+ return sel.getRangeAt(0);
+ }
+ } else if (document.selection) {
+ return document.selection.createRange();
+ }
+ return null;
+}
+
+export function getSelectedHtmlInfo() {
+ const selectRange = getSelectionHtmlRange();
+ if (!selectRange) return {};
+
+ // if (selectRange.startContainer !== selectRange.endContainer) {
+ // return;
+ // }
+
+ let begin = 0;
+ let strBegin = "";
+ let prevFullText = "";
+ if (selectRange.startOffset > 0)
+ strBegin = selectRange.startContainer.textContent.substring(
+ 0,
+ selectRange.startOffset - 1
+ );
+
+ // برای وقتی که در تگ قبلی ، شماره کلمه انتها ذخیره شده است و نیازی به بررسی قبل از آن نیست
+ if (
+ selectRange.commonAncestorContainer.previousSibling &&
+ selectRange.commonAncestorContainer.previousSibling.dataset?.end
+ ) {
+ begin =
+ parseInt(
+ selectRange.commonAncestorContainer.previousSibling.dataset.end
+ ) + 1;
+ begin += splitWord(strBegin).length;
+ } else {
+ prevFullText = getPreviousHtmlText(selectRange.startContainer, selectRange);
+ begin += splitWord(prevFullText).length;
+ }
+
+ let selectedText = selectRange.startContainer.textContent.substring(
+ selectRange.startOffset,
+ selectRange.endOffset
+ );
+ let end = begin + splitWord(selectedText).length - 1;
+
+ ///////////////////////////////////////////////////////
+ ///// استخراج کلمه کلیک شده و دو کلمه بعدش
+ ///// برای حالتی که متنی انتخاب نشده و فقط کلیک شده نیاز هست
+
+ let node = selectRange.startContainer;
+ const fullText = node.textContent;
+ const offset = selectRange.startOffset;
+
+ const words = fullText.split(/\s+/);
+ let totalChars = 0;
+ let wordIndex = -1;
+ let wordsClicked = "";
+
+ /// چون احتمال داره وسط کلمه کلیک شده باشه، قبل کلمه کلیک شده می ایستیم
+ for (let i = 0; i < words.length; i++) {
+ totalChars += words[i].length + 1;
+ if (offset < totalChars) {
+ wordIndex = i;
+ break;
+ }
+ }
+
+ if (wordIndex !== -1) {
+ wordsClicked =
+ words[wordIndex] +
+ " " +
+ (words[wordIndex + 1] || "") +
+ " " +
+ (words[wordIndex + 2] || "");
+ }
+ ///////////////////////////////////////////////////////
+
+ let info = {
+ begin: begin,
+ end: end,
+ selectedText: selectedText,
+ prevTextBegin: strBegin,
+ texts: wordsClicked,
+ // prevTextFull: prevFullText,
+ };
+ return info;
+}
+
+export function getPreviousHtmlText(node, selectRange = null) {
+ let text = "";
+ if (!node) return text;
+ else if (selectRange && node == selectRange.startContainer) {
+ if (selectRange.startOffset > 0)
+ text = selectRange.startContainer.textContent.substring(
+ 0,
+ selectRange.startOffset - 1
+ );
+ // else
+ // text = selectRange.startContainer.textContent;
+ } else text = node.textContent;
+
+ if (node.previousSibling)
+ text = getPreviousHtmlText(node.previousSibling, null) + text;
+
+ return text;
+}
+////////////////////////////////////////////////////////////////////
+
+export function splitWord(text) {
+ let items = text.split(
+ /[\t\n\r\.\'\"«»\)\(\]\[\{\}\%\#\$\*\<\>\/,;،؛ \-!?:٭؟]+/
+ );
+ // let items = text.split("\t\n\r.'\"«»)(][{}%#$*<>/,;،؛ -!?:٭؟")
+ return items;
+}
+
+export function normalizeText(
+ text,
+ options = { charArNormal: true, errorLine: true }
+) {
+ // //defualt
+ // options = {
+ // charArNormal: true,
+ // errorLine: true,
+ // alphabetsNormal: false,
+ // emptylinesNormal: false,
+ // hamzehNormal: false,
+ // spaceCorrection: false,
+ // trimLine: false
+ // };
+
+ text = text.trim();
+
+ //اصلاح خطاهای متن در کد خط
+ if (options?.errorLine) {
+ text = text.replaceAll("\\n", "\n");
+ text = text.replaceAll("\\r", "\r");
+ text = replaceRegText("(\r\n)+", "\n", text);
+ text = text.replaceAll("\r", "\n");
+
+ //شنبهها ==> شنبهها
+ //رسیدگیهای ==> رسیدگیهای
+ // text = replaceRegText("(ه)(ها)", /\1\2/gm, text);
+ }
+ // یکسان سازی اختلاف حروف کیبوردهای مختلف - کدهای مختلف ولی نمایش یکسان
+ if (options?.alphabetsNormal) {
+ text = replaceAlphabets(text);
+ }
+
+ //حذف خطوط و فاصلههای خالی
+ if (options?.emptylinesNormal) {
+ text = replaceRegText("( )+", " ", text);
+ text = replaceRegText("(\n)+", "\n", text);
+ }
+
+ // نرمال کردن حروف اختلافی عربی و فارسی
+ if (options?.charArNormal) {
+ text = text.replaceAll("ي", "ی");
+ text = text.replaceAll("ك", "ک");
+ }
+
+ // پرش از اختلافات همزهای
+ if (options?.hamzehNormal) {
+ text = replaceRegText("ئ|ﺋ", "ی", text);
+ text = replaceRegText("ؤ|ﺅ", "و", text);
+ text = replaceRegText("ﺔ|ۀ|ة", "ه", text);
+ text = replaceRegText("إ|أ", "ا", text);
+ }
+ if (options?.dateNormal) {
+ text = dateNormalize(text);
+ }
+ if (options?.spaceCorrection) {
+ text = spaceCorrection(text);
+ }
+
+ // حذف خطوط اضافی اول و انتهای متن
+ if (options?.trimLine) text = text.replace(/^\s+|\s+$/g, "");
+
+ text = text.trim();
+
+ return text;
+}
+
+//برعکس بودن تاریخ ها را درست میکند
+export function dateNormalize(text, forWord = false) {
+ if (forWord) {
+ // فرمت YYYY/MM/DD یا YYYY-MM-DD
+ text = replaceRegText(
+ /(\d{4})[\/\-](\d{1,2})[\/\-](\d{1,2})/,
+ (_, year, month, day) =>
+ `${day.padStart(2, "0")}/${month.padStart(2, "0")}/${year}`,
+ text
+ );
+
+ // // فرمت DD/MM/YYYY یا DD-MM-YYYY
+ // text = replaceRegText(
+ // /(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{4})/,
+ // (_, day, month, year) =>
+ // `${year}/${month.padStart(2, "0")}/${day.padStart(2, "0")}`,
+ // text
+ // );
+ } else {
+ // فرمت YYYY/MM/DD یا YYYY-MM-DD
+ text = replaceRegText(
+ /(\d{4})[\/\-](\d{1,2})[\/\-](\d{1,2})/,
+ (_, year, month, day) =>
+ `${year}/${month.padStart(2, "0")}/${day.padStart(2, "0")}`,
+ text
+ );
+
+ // فرمت DD/MM/YYYY یا DD-MM-YYYY
+ text = replaceRegText(
+ /(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{4})/,
+ (_, day, month, year) =>
+ `${year}/${month.padStart(2, "0")}/${day.padStart(2, "0")}`,
+ text
+ );
+ }
+
+ // // فرمت MM/DD/YYYY
+ // text = replaceRegText(
+ // /(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{4})/,
+ // (_, month, day, year) =>
+ // `${year}/${month.padStart(2, "0")}/${day.padStart(2, "0")}`,
+ // text
+ // );
+ return text;
+}
+
+export function replaceAlphabets(text) {
+ let res = text;
+ res = res.replaceAll("\u00AD", "\u200C");
+ res = res.replaceAll("\u00AC", "\u200C"); // نیم اسپیس خاص
+
+ res = replaceRegText("ﺁ|آ", "آ", res);
+ res = replaceRegText("ﺎ|ٱ|ﺍ", "ا", res); //
+ res = replaceRegText("ٲ|أ|ﺄ|ﺃ", "أ", res);
+ res = replaceRegText("ﺈ|ﺇ", "إ", res);
+ res = replaceRegText("ﺐ|ﺏ|ﺑ|ﺒ", "ب", res);
+ res = replaceRegText("ﭖ|ﭗ|ﭙ|ﭘ", "پ", res);
+ res = replaceRegText("ﭡ|ٺ|ٹ|ﭞ|ٿ|ټ|ﺕ|ﺗ|ﺖ|ﺘ", "ت", res);
+ res = replaceRegText("ﺙ|ﺛ|ﺚ|ﺜ", "ث", res);
+ res = replaceRegText("ﺝ|ڃ|ﺠ|ﺟ", "ج", res);
+ res = replaceRegText("ڃ|ﭽ|ﭼ", "چ", res);
+ res = replaceRegText("ﺢ|ﺤ|څ|ځ|ﺣ", "ح", res);
+ res = replaceRegText("ﺥ|ﺦ|ﺨ|ﺧ", "خ", res);
+ res = replaceRegText("ڏ|ډ|ﺪ|ﺩ", "د", res);
+ res = replaceRegText("ﺫ|ﺬ|ذ", "ذ", res);
+ res = replaceRegText("ڙ|ڗ|ڒ|ڑ|ڕ|ﺭ|ﺮ", "ر", res);
+ res = replaceRegText("ﺰ|ﺯ", "ز", res);
+ res = replaceRegText("ﮊ", "ژ", res);
+ res = replaceRegText("ݭ|ݜ|ﺱ|ﺲ|ښ|ﺴ|ﺳ", "س", res);
+ res = replaceRegText("ﺵ|ﺶ|ﺸ|ﺷ", "ش", res);
+ res = replaceRegText("ﺺ|ﺼ|ﺻ|ﺹ", "ص", res); //
+ res = replaceRegText("ﺽ|ﺾ|ﺿ|ﻀ", "ض", res);
+ res = replaceRegText("ﻁ|ﻂ|ﻃ|ﻄ", "ط", res);
+ res = replaceRegText("ﻆ|ﻇ|ﻈ", "ظ", res);
+ res = replaceRegText("ڠ|ﻉ|ﻊ|ﻋ|ﻌ", "ع", res);
+ res = replaceRegText("ﻎ|ۼ|ﻍ|ﻐ|ﻏ", "غ", res);
+ res = replaceRegText("ﻒ|ﻑ|ﻔ|ﻓ", "ف", res);
+ res = replaceRegText("ﻕ|ڤ|ﻖ|ﻗ|ﻘ", "ق", res);
+ res = replaceRegText("ڭ|ﻚ|ﮎ|ﻜ|ﮏ|ګ|ﻛ|ﮑ|ﮐ|ڪ|ك", "ک", res);
+ res = replaceRegText("ﮚ|ﮒ|ﮓ|ﮕ|ﮔ", "گ", res);
+ res = replaceRegText("ﻝ|ﻞ|ﻠ|ڵ|ﻟ", "ل", res); //
+ res = replaceRegText("ﻵ|ﻶ|ﻷ|ﻸ|ﻹ|ﻺ|ﻻ|ﻼ", "لا", res); //
+ res = replaceRegText("ﻡ|ﻤ|ﻢ|ﻣ", "م", res);
+ res = replaceRegText("ڼ|ﻦ|ﻥ|ﻨ|ﻧ", "ن", res);
+ res = replaceRegText("ވ|ﯙ|ۈ|ۋ|ﺆ|ۊ|ۇ|ۏ|ۅ|ۉ|ﻭ|ﻮ|ؤ", "و", res);
+ res = replaceRegText("ﻬ|ھ|ﻩ|ﻫ|ﻪ|ە|ہ", "ه", res);
+ res = replaceRegText("ﭛ|ﻯ|ۍ|ﻰ|ﻱ|ﻲ|ں|ﻳ|ﻴ|ﯼ|ې|ﯽ|ﯾ|ﯿ|ێ|ے|ى|ي", "ی", res);
+ res = replaceRegText("¬", "", res);
+ res = replaceRegText("•|·|●|·|・|∙|。|ⴰ", ".", res);
+ res = replaceRegText(",|٬|٫|‚|،", "،", res);
+ res = replaceRegText("ʕ", "؟", res);
+ res = replaceRegText("۰|٠", "0", res);
+ res = replaceRegText("۱|١", "1", res);
+ res = replaceRegText("۲|٢", "2", res);
+ res = replaceRegText("۳|٣", "3", res);
+ res = replaceRegText("۴|٤", "4", res);
+ res = replaceRegText("۵", "5", res);
+ res = replaceRegText("۶|٦", "6", res);
+ res = replaceRegText("۷|٧", "7", res);
+ res = replaceRegText("۸|٨", "8", res);
+ res = replaceRegText("۹|٩", "9", res);
+ res = replaceRegText("²", "2", res);
+ res = replaceRegText("|ِ|ُ|َ|ٍ|ٌ|ً|", "", res);
+ // res = replaceRegText("ـ", "_", res);
+ res = replaceRegText("ـ", "-", res); //
+
+ // res = replaceRegText("([\u0600-\u06FF])ـ([\u0600-\u06FF])", "\1\2", res) // حذف حروف کشیده
+ // res = replaceRegText("([\u0600-\u06FF])ـ", "\1", res) // حذف حروف کشیده
+
+ res = res.replace(/\u200C+$/, "");
+ res = res.trim();
+
+ return res;
+}
+
+export function spaceCorrection(text) {
+ let res = text;
+ res = replaceRegText("^(بی|می|نمی)( )", "$1", res);
+ res = replaceRegText("( )(می|نمی|بی)( )", "$1$2", res);
+ res = replaceRegText(
+ "( )(هایی|ها|های|ایی|هایم|هایت|هایش|هایمان|هایتان|هایشان|ات|ان|ین|انی|بان|ام|ای|یم|ید|اید|اند|بودم|بودی|بود|بودیم|بودید|بودند|ست)( )",
+ "$2$3",
+ res
+ );
+ res = replaceRegText("( )(شده|نشده)( )", "$2", res);
+ res = replaceRegText(
+ "( )(طلبان|طلب|گرایی|گرایان|شناس|شناسی|گذاری|گذار|گذاران|شناسان|گیری|پذیری|بندی|آوری|سازی|بندی|کننده|کنندگان|گیری|پرداز|پردازی|پردازان|آمیز|سنجی|ریزی|داری|دهنده|آمیز|پذیری|پذیر|پذیران|گر|ریز|ریزی|رسانی|یاب|یابی|گانه|گانهای|انگاری|گا|بند|رسانی|دهندگان|دار)( )",
+ "$2$3",
+ res
+ );
+ return res;
+}
+
+export function replaceRegText(pattern, replacement, text) {
+ const regex = new RegExp(pattern, "g");
+ return text.replace(regex, replacement);
+}
+
+export function generateUID() {
+ // I generate the UID from two parts here
+ // to ensure the random number provide enough bits.
+ var firstPart = (Math.random() * 46656) | 0;
+ var secondPart = (Math.random() * 46656) | 0;
+ firstPart = ("000" + firstPart.toString(36)).slice(-3);
+ secondPart = ("000" + secondPart.toString(36)).slice(-3);
+ return firstPart + secondPart; // eg : 9c8yxr
+}
+
+function myEncodeQuery(text) {
+ if (!text || text == "") return "";
+ //text = JSON.stringify(text);
+ let ch1 = encodeURIComponent("#");
+ let ch3 = encodeURIComponent("\\");
+ let ch4 = encodeURIComponent("&");
+ text = text.replaceAll("#", ch1);
+ text = text.replaceAll("&", ch4);
+ text = text.replaceAll("/", "\\");
+ text = text.replaceAll("\\", ch3);
+
+ // با تبدیل نقطه مشکل نشانی درخواست در بک حل نشد
+ //text = text.replaceAll(".", '%2E');
+ return text;
+}
+
+export function cleanTextUnpermittedChars(text) {
+ if (!text) return "";
+
+ text = text.replaceAll("([0x0000-0x001F]|(0x007F))", "");
+ return text;
+}
+
+
+// utils/tree.js
+export function findNodeWithPath(nodes, targetId, path = []) {
+ for (let i = 0; i < nodes.length; i++) {
+ const node = nodes[i];
+ const currentPath = [...path, i];
+
+ // ✅ Adjust this condition based on how you identify a node
+ if (node.id === targetId) {
+ return { node, path: currentPath };
+ }
+
+ // Recurse into children if they exist
+ if (node.children && node.children.length > 0) {
+ const result = findNodeWithPath(node.children, targetId, currentPath);
+ if (result) return result;
+ }
+ }
+ return null; // Not found
+}
+
+export function updateNodeByPath(nodes, path, newValue) {
+ let current = nodes;
+ // Navigate to the parent of the target node
+ for (let i = 0; i < path.length - 1; i++) {
+ current = current[path[i]].children;
+ }
+ // Update the target node
+ const targetIndex = path[path.length - 1];
+ current[targetIndex] = { ...current[targetIndex], ...newValue };
+}
+
+//////////////////////////////////////////
+
+// export { wait, handleErrors }
diff --git a/app/pages/index.vue b/app/pages/index.vue
index 4494b96..8ef405c 100755
--- a/app/pages/index.vue
+++ b/app/pages/index.vue
@@ -13,6 +13,7 @@
:is="currentComponent"
v-if="currentComponent"
:activeTabKey="activeTabKey"
+ :listConflicts="listConflicts"
/>