295 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			295 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| /*
 | ||
|     Парус 8 - Панели мониторинга - УДП - Доски задач
 | ||
|     Дополнительная разметка и вёрстка клиентских элементов
 | ||
| */
 | ||
| 
 | ||
| //---------
 | ||
| //Константы
 | ||
| //---------
 | ||
| 
 | ||
| //Перечисление "Состояние события"
 | ||
| export const EVENT_STATES = Object.freeze({ 0: "Все", 1: "Не аннулированные", 2: "Аннулированные" });
 | ||
| 
 | ||
| //Допустимые значение поля сортировки
 | ||
| export const sortAttrs = [
 | ||
|     { id: "SEVNSTAT_CODE", descr: "Мнемокод" },
 | ||
|     { id: "SEVNSTAT_NAME", descr: "Наименование" },
 | ||
|     { id: "SEVPOINT_DESCR", descr: "Описание точки маршрута" }
 | ||
| ];
 | ||
| 
 | ||
| //Допустимые значения направления сортировки
 | ||
| export const sortDest = [];
 | ||
| sortDest[-1] = "desc";
 | ||
| sortDest[1] = "asc";
 | ||
| 
 | ||
| //Цвета статусов
 | ||
| export const COLORS = [
 | ||
|     "mediumSlateBlue",
 | ||
|     "lightSalmon",
 | ||
|     "fireBrick",
 | ||
|     "orange",
 | ||
|     "gold",
 | ||
|     "limeGreen",
 | ||
|     "yellowGreen",
 | ||
|     "mediumAquaMarine",
 | ||
|     "paleTurquoise",
 | ||
|     "steelBlue",
 | ||
|     "skyBlue",
 | ||
|     "tan"
 | ||
| ];
 | ||
| 
 | ||
| //Перечисление "Цвет задачи"
 | ||
| export const TASK_COLORS = Object.freeze({ EXPIRED: "#ff0000", EXPIRES_SOON: "#ffdf00", LINKED: "#1e90ff" });
 | ||
| 
 | ||
| //Перечисление Доп. свойства "Значение по умолчанию"
 | ||
| export const DP_DEFAULT_VALUE = Object.freeze({ 0: "SDEFAULT_STR", 1: "NDEFAULT_NUM", 2: "DDEFAULT_DATE", 3: "NDEFAULT_NUM" });
 | ||
| //Перечисление Доп. свойства "Префикс формата данных"
 | ||
| export const DP_TYPE_PREFIX = Object.freeze({ 0: "S", 1: "N", 2: "D", 3: "N" });
 | ||
| //Перечисление Доп. свойства "Входящее значение дополнительного словаря"
 | ||
| export const DP_IN_VALUE = Object.freeze({ 0: "pos_str_value", 1: "pos_num_value", 2: "pos_date_value", 3: "pos_num_value" });
 | ||
| //Перечисление Доп. свойства "Исходящее значение дополнительного словаря"
 | ||
| export const DP_RETURN_VALUE = Object.freeze({ 0: "str_value", 1: "num_value", 2: "date_value", 3: "num_value" });
 | ||
| 
 | ||
| //-----------
 | ||
| //Тело модуля
 | ||
| //-----------
 | ||
| 
 | ||
| //Формирование массива из 0, 1 и более элементов
 | ||
| export const makeArray = arr => {
 | ||
|     return arr ? (arr.length ? arr : [arr]) : [];
 | ||
| };
 | ||
| 
 | ||
| //Конвертация формата HEX в формат RGB
 | ||
| const convertHexToRGB = hex => {
 | ||
|     let r = parseInt(hex.slice(1, 3), 16);
 | ||
|     let g = parseInt(hex.slice(3, 5), 16);
 | ||
|     let b = parseInt(hex.slice(5, 7), 16);
 | ||
|     let a = 0.5;
 | ||
|     r = Math.round((a * (r / 255) + a * (255 / 255)) * 255);
 | ||
|     g = Math.round((a * (g / 255) + a * (255 / 255)) * 255);
 | ||
|     b = Math.round((a * (b / 255) + a * (255 / 255)) * 255);
 | ||
|     return "rgb(" + r + ", " + g + ", " + b + ")";
 | ||
| };
 | ||
| 
 | ||
| //Считывание заливки события по условию
 | ||
| export const getTaskBgColorByRule = (task, colorRule) => {
 | ||
|     //Инициализируем значения
 | ||
|     let ruleCode = "";
 | ||
|     //Исходя из типа определяем наименование
 | ||
|     switch (colorRule.STYPE) {
 | ||
|         case "number":
 | ||
|             ruleCode = `N${colorRule.SFIELD}`;
 | ||
|             break;
 | ||
|         case "date":
 | ||
|             ruleCode = `D${colorRule.SFIELD}`;
 | ||
|             break;
 | ||
|         default:
 | ||
|             ruleCode = `S${colorRule.SFIELD}`;
 | ||
|             break;
 | ||
|     }
 | ||
|     //Определяем цвет заливки
 | ||
|     let bgColor = ruleCode && task.docProps[ruleCode] == colorRule.fromValue ? convertHexToRGB(colorRule.SCOLOR) : null;
 | ||
|     //Возвращаем цвет заливки
 | ||
|     return bgColor;
 | ||
| };
 | ||
| 
 | ||
| //Индикация истечения срока отработки события
 | ||
| export const getTaskExpiredColor = task => {
 | ||
|     //Определяем текущую дату
 | ||
|     let sysDate = new Date();
 | ||
|     //Определяем дату истечения срока события
 | ||
|     let expireDate = task.dExpireDate ? new Date(task.dExpireDate) : null;
 | ||
|     //Если дата истечения срока определена
 | ||
|     if (expireDate) {
 | ||
|         //Определяем разницу между датами
 | ||
|         let daysDiff = ((expireDate.getTime() - sysDate.getTime()) / (1000 * 60 * 60 * 24)).toFixed(2);
 | ||
|         //Если разница меньше 0 - срок истечен
 | ||
|         if (daysDiff < 0) return TASK_COLORS.EXPIRED;
 | ||
|         //Если разница меньше 4 - скоро истечет
 | ||
|         if (daysDiff < 4) return TASK_COLORS.EXPIRES_SOON;
 | ||
|     }
 | ||
|     return null;
 | ||
| };
 | ||
| 
 | ||
| //Цвет из hsl формата в rgba формат
 | ||
| const convertHslToRgba = (h, s, l) => {
 | ||
|     s /= 100;
 | ||
|     l /= 100;
 | ||
|     const k = n => (n + h / 30) % 12;
 | ||
|     const a = s * Math.min(l, 1 - l);
 | ||
|     const f = n => l - a * Math.max(-1, Math.min(k(n) - 3, Math.min(9 - k(n), 1)));
 | ||
|     return `rgba(${Math.floor(255 * f(0))},${Math.floor(255 * f(8))},${Math.floor(255 * f(4))},0.3)`;
 | ||
| };
 | ||
| 
 | ||
| //Формирование случайного цвета
 | ||
| export const getRandomColor = index => {
 | ||
|     const hue = index * 137.508;
 | ||
|     return convertHslToRgba(hue, 50, 70);
 | ||
| };
 | ||
| 
 | ||
| //Формат дополнительного свойства типа число (длина, точность)
 | ||
| const formatRegExpNum = (width, precision) =>
 | ||
|     new RegExp("^(\\d{1," + (width - precision) + "}" + (precision > 0 ? "((\\.|,)\\d{1," + precision + "})?" : "") + ")?$");
 | ||
| 
 | ||
| //Формат дополнительного свойства типа строка (длина)
 | ||
| const formatRegExpStr = length => new RegExp("^.{0," + length + "}$");
 | ||
| 
 | ||
| //Проверка валидности числа
 | ||
| const isValidNum = (width, precision, value) => {
 | ||
|     return formatRegExpNum(width, precision).test(value);
 | ||
| };
 | ||
| 
 | ||
| //Проверка валидности строки
 | ||
| const isValidStr = (length, value) => {
 | ||
|     return formatRegExpStr(length).test(value);
 | ||
| };
 | ||
| 
 | ||
| //Признак ошибки валидации
 | ||
| export const validationError = (value = "", format, numWidth, numPrecision, strLength) => {
 | ||
|     //Исходим от формата
 | ||
|     switch (format) {
 | ||
|         //Проверка строки
 | ||
|         case 0:
 | ||
|             return isValidStr(strLength, value);
 | ||
|         //Проверка числа
 | ||
|         case 1:
 | ||
|             return isValidNum(numWidth, numPrecision, value);
 | ||
|         //Остальное не проверяем
 | ||
|         default:
 | ||
|             return true;
 | ||
|     }
 | ||
| };
 | ||
| 
 | ||
| //Конвертация времени в привычный формат
 | ||
| export const formatSqlDate = timeStamp => {
 | ||
|     //Если есть разделитель
 | ||
|     if (timeStamp.indexOf(".") !== -1) {
 | ||
|         //Определяем секунды
 | ||
|         let seconds = 24 * 60 * 60 * timeStamp;
 | ||
|         //Определяем часы
 | ||
|         const hours = Math.trunc(seconds / (60 * 60));
 | ||
|         //Переопределяем секунды
 | ||
|         seconds = seconds % (60 * 60);
 | ||
|         //Определяем минуты
 | ||
|         const minutes = Math.trunc(seconds / 60);
 | ||
|         //Определяем остаток секунд
 | ||
|         seconds = Math.round(seconds % 60);
 | ||
|         //Форматируем
 | ||
|         const formattedTime = ("0" + hours).slice(-2) + ":" + ("0" + minutes).slice(-2) + ":" + ("0" + seconds).slice(-2);
 | ||
|         //Возвращаем результат
 | ||
|         return formattedTime;
 | ||
|     }
 | ||
|     return timeStamp;
 | ||
| };
 | ||
| 
 | ||
| //Считывание значений из локального хранилища
 | ||
| export const getLocalStorageValue = (sName, defaultValue = null) => {
 | ||
|     return localStorage.getItem(sName) ? localStorage.getItem(sName) : defaultValue;
 | ||
| };
 | ||
| 
 | ||
| //Форматирование фильтра в массив для отбора
 | ||
| export const convertFilterValuesToArray = filterValues => {
 | ||
|     //Инициализируем значение "с" состояния ("Все", "Не аннулированные" - 0, "Аннулированые" - 1)
 | ||
|     let nClosedFrom = filterValues.sState ? ([EVENT_STATES[0], EVENT_STATES[1]].includes(filterValues.sState) ? 0 : 1) : 0;
 | ||
|     //Инициализируем значение "по" состояния ("Все", "Аннулированные" - 1, "Не аннулированные" - 0)
 | ||
|     let nClosedTo = filterValues.sState ? ([EVENT_STATES[0], EVENT_STATES[2]].includes(filterValues.sState) ? 1 : 0) : 0;
 | ||
|     //Формируем массив значений фильтра
 | ||
|     let filterValuesArray = [
 | ||
|         { name: "NCLOSED", from: nClosedFrom, to: nClosedTo },
 | ||
|         { name: "SEVTYPE_CODE", from: filterValues.sType, to: null },
 | ||
|         { name: "NCRN", from: filterValues.sCrnRnList, to: null },
 | ||
|         { name: "SSEND_PERSON", from: filterValues.sSendPerson, to: null },
 | ||
|         { name: "SSEND_DIVISION", from: filterValues.sSendDivision, to: null },
 | ||
|         { name: "SSEND_USRGRP", from: filterValues.sSendUsrGrp, to: null },
 | ||
|         { name: "NLINKED_RN", from: filterValues.sDocLink, to: null }
 | ||
|     ];
 | ||
|     return filterValuesArray;
 | ||
| };
 | ||
| 
 | ||
| //Формирование массива действий карточки события
 | ||
| export const makeCardActionsArray = (onEdit, onEditClient, onDelete, onStateChange, onReturn, onSend, onNotesOpen, onFileLinksOpen) => {
 | ||
|     //Формируем список действий карточки
 | ||
|     return [
 | ||
|         {
 | ||
|             method: "EDIT",
 | ||
|             name: "Исправить",
 | ||
|             icon: "edit",
 | ||
|             visible: false,
 | ||
|             delimiter: false,
 | ||
|             tasksReload: false,
 | ||
|             needAccountsReload: false,
 | ||
|             func: onEdit
 | ||
|         },
 | ||
|         {
 | ||
|             method: "EDIT_CLIENT",
 | ||
|             name: "Исправить в разделе",
 | ||
|             icon: "edit_note",
 | ||
|             visible: true,
 | ||
|             delimiter: false,
 | ||
|             tasksReload: false,
 | ||
|             needAccountsReload: false,
 | ||
|             func: onEditClient
 | ||
|         },
 | ||
|         {
 | ||
|             method: "DELETE",
 | ||
|             name: "Удалить",
 | ||
|             icon: "delete",
 | ||
|             visible: true,
 | ||
|             delimiter: true,
 | ||
|             tasksReload: true,
 | ||
|             needAccountsReload: false,
 | ||
|             func: onDelete
 | ||
|         },
 | ||
|         {
 | ||
|             method: "TASK_STATE_CHANGE",
 | ||
|             name: "Перейти",
 | ||
|             icon: "turn_right",
 | ||
|             visible: true,
 | ||
|             delimiter: false,
 | ||
|             tasksReload: true,
 | ||
|             needAccountsReload: true,
 | ||
|             func: onStateChange
 | ||
|         },
 | ||
|         {
 | ||
|             method: "TASK_RETURN",
 | ||
|             name: "Выполнить возврат",
 | ||
|             icon: "turn_left",
 | ||
|             visible: true,
 | ||
|             delimiter: false,
 | ||
|             tasksReload: true,
 | ||
|             needAccountsReload: true,
 | ||
|             func: onReturn
 | ||
|         },
 | ||
|         {
 | ||
|             method: "TASK_SEND",
 | ||
|             name: "Направить",
 | ||
|             icon: "send",
 | ||
|             visible: true,
 | ||
|             delimiter: true,
 | ||
|             tasksReload: true,
 | ||
|             needAccountsReload: true,
 | ||
|             func: onSend
 | ||
|         },
 | ||
|         {
 | ||
|             method: "NOTES",
 | ||
|             name: "Примечания",
 | ||
|             icon: "event_note",
 | ||
|             visible: true,
 | ||
|             delimiter: true,
 | ||
|             tasksReload: false,
 | ||
|             needAccountsReload: false,
 | ||
|             func: onNotesOpen
 | ||
|         },
 | ||
|         {
 | ||
|             method: "FILE_LINKS",
 | ||
|             name: "Присоединенные документы",
 | ||
|             icon: "attach_file",
 | ||
|             visible: true,
 | ||
|             delimiter: false,
 | ||
|             tasksReload: false,
 | ||
|             needAccountsReload: false,
 | ||
|             func: onFileLinksOpen
 | ||
|         }
 | ||
|     ];
 | ||
| };
 |