• הרשמה
    • התחברות
    • חיפוש
    • דף הבית
    • אינדקס קישורים
    • פוסטים אחרונים
    • קבלת התראות מהדפדפן
    • משתמשים
    • חיפוש בהגדרות המתקדמות
    • חיפוש גוגל בפורום
    • ניהול המערכת
    • ניהול המערכת - שרת private

    קבצים ותוכנות לשימוש במערכות ימות המשיח

    עזרה הדדית למשתמשים מתקדמים
    5
    19
    294
    טוען פוסטים נוספים
    • מהישן לחדש
    • מהחדש לישן
    • הכי הרבה הצבעות
    תגובה
    • הגיבו כנושא
    התחברו בכדי לפרסם תגובה
    נושא זה נמחק. רק משתמשים עם הרשאות מתאימות יוכלו לצפות בו.
    • א
      אA נערך לאחרונה על ידי אA

      קובץ להפעלת קמפיין - הנכנס לשלוחה במערכת

      הפעלת קמפיין - הנכנס לשלוחה במערכת.html

      הקוד מצורף בספויילר

      <!DOCTYPE html>
      <html lang="he" dir="rtl">
      <head>
      <meta charset="UTF-8">
      <title>שיגור קמפיין - הנכנס לשלוחה במערכת</title>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js"></script>
      <style>
      :root {
      --primary-color: #4a90e2;
      --success-color: #27ae60;
      --error-color: #e74c3c;
      --border-radius: 12px;
      }

          body { 
              font-family: 'Segoe UI', Arial, sans-serif; 
              background-color: #f4f7f9;
              margin: 0; padding: 20px; color: #333;
          }
      
          .container { 
              max-width: 600px; margin: auto; background: white;
              padding: 30px; border-radius: var(--border-radius); 
              box-shadow: 0 4px 15px rgba(0,0,0,0.1); 
          }
      
          h2 { 
              text-align: center; 
              color: var(--primary-color);
              display: flex; 
              align-items: center;
              justify-content: center;
              gap: 10px; 
              margin-bottom: 25px;
          }
      
          .speaker-icon {
              width: 30px; height: 30px;
              background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="%234a90e2"><path d="M14 3.23v17.54c0 .87-.98 1.34-1.6.84L7.37 15H2c-1.1 0-2-.9-2-2v-2c0-1.1.9-2 2-2h5.37L12.4 2.39c.62-.5 1.6-.03 1.6.84zM16.5 12c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM19 12c0 2.97-1.87 5.51-4.5 6.74v-13.48c2.63 1.23 4.5 3.77 4.5 6.74z"/></svg>');
              background-repeat: no-repeat; background-position: center; background-size: contain;
          }
      
          .form-group { margin-bottom: 15px; }
          label { display: block; font-weight: bold; margin-bottom: 5px; }
          input, textarea { 
              width: 100%; padding: 10px; border: 1px solid #ddd; border-radius: 8px; box-sizing: border-box; 
          }
      
          .type-selector {
              display: flex; gap: 15px; margin-bottom: 15px; background: #f9f9f9; padding: 10px; border-radius: 8px;
          }
          .type-selector label { font-weight: normal; cursor: pointer; display: flex; align-items: center; gap: 5px; margin: 0; }
      
          .ivr-input-wrapper { display: flex; direction: ltr; border: 1px solid #ddd; border-radius: 8px; overflow: hidden; }
          .ivr-prefix { background: #eee; padding: 10px; border-right: 1px solid #ddd; font-weight: bold; }
          .ivr-input-wrapper input { border: none; flex: 1; outline: none; }
      
          button { 
              background-color: var(--success-color); color: white; border: none; 
              padding: 15px; cursor: pointer; border-radius: 8px; width: 100%; 
              font-size: 18px; font-weight: bold; margin-top: 10px;
          }
      
          button:active { transform: scale(0.98); }
          button:disabled { background-color: #ccc; cursor: not-allowed; }
      
          #error-display { 
              margin-top: 15px; padding: 15px; background: #fff5f5; 
              border: 1px solid var(--error-color); border-radius: 8px; 
              color: var(--error-color); display: none; font-size: 14px;
          }
      
          .modal {
              display: none; position: fixed; z-index: 1000; left: 0; top: 0; 
              width: 100%; height: 100%; background: rgba(0,0,0,0.6); backdrop-filter: blur(3px);
          }
      
          .modal-content {
              background: white; margin: 15% auto; padding: 25px; 
              border-radius: var(--border-radius); width: 90%; max-width: 450px;
              text-align: center; box-shadow: 0 8px 25px rgba(0,0,0,0.2);
          }
      
          table { width: 100%; border-collapse: collapse; margin-top: 15px; direction: rtl; }
          th, td { border: 1px solid #ddd; padding: 10px; text-align: right; }
          th { background: #f9f9f9; }
          
          .close-btn { background: #666; color: white; padding: 8px 20px; border: none; border-radius: 5px; cursor: pointer; margin-top: 15px; }
      </style>
      

      </head>
      <body>

      <div class="container">
      <h2>
      <div class="speaker-icon"></div>
      שיגור קמפיין - הנכנס לשלוחה
      </h2>

      <div class="form-group">
          <label>טוקן (Token):</label>
          <input type="text" id="token" placeholder="הכנס טוקן API">
      </div>
      
      <div class="form-group">
          <label>סוג יעד:</label>
          <div class="type-selector">
              <label><input type="radio" name="targetType" value="manual" checked onchange="updateUI()"> רשימת מספרים</label>
              <label><input type="radio" name="targetType" value="tpl" onchange="updateUI()"> רשימת תפוצה</label>
              <label><input type="radio" name="targetType" value="tzl" onchange="updateUI()"> רשימת צינתוקים</label>
          </div>
      </div>
      
      <div class="form-group" id="excelGroup">
          <label>טעינת אקסל (אופציונלי):</label>
          <input type="file" id="excelFile" accept=".xlsx, .xls, .csv">
      </div>
      
      <div class="form-group">
          <label id="targetLabel">מספרי טלפון:</label>
          <textarea id="targetInput" rows="4" placeholder="מספר בכל שורה"></textarea>
      </div>
      
      <div class="form-group">
          <label>שלוחה במערכת:</label>
          <div class="ivr-input-wrapper">
              <span class="ivr-prefix">ivr2:</span>
              <input type="text" id="ivrPath" placeholder="/1/100">
          </div>
      </div>
      
      <div class="form-group">
          <label>זיהוי שיחה (Caller ID) - אופציונלי:</label>
          <input type="text" id="callerId" placeholder="ברירת מחדל">
      </div>
      
      <div class="form-group">
          <label>זמן המתנה (30-35 שניות):</label>
          <input type="number" id="callsTimeOut" value="30" min="30" max="35">
      </div>
      
      <button id="submitBtn" onclick="sendCampaign()">שיגור קמפיין</button>
      <div id="error-display"></div>
      

      </div>

      <div id="successModal" class="modal">
      <div class="modal-content">
      <h3 style="color: var(--success-color);">הקמפיין נוצר בהצלחה!</h3>
      <table id="resultTable"></table>
      <button class="close-btn" onclick="closeModal()">סגור</button>
      </div>
      </div>

      <script>
      function updateUI() {
      const type = document.querySelector('input[name="targetType"]:checked').value;
      const inputArea = document.getElementById('targetInput');
      const excelGroup = document.getElementById('excelGroup');
      const label = document.getElementById('targetLabel');

          inputArea.value = ''; // ניקוי התיבה במעבר בין סוגים
      
          if (type === 'manual') {
              label.innerText = 'מספרי טלפון:';
              inputArea.placeholder = 'מספר בכל שורה';
              excelGroup.style.display = 'block';
          } else if (type === 'tpl') {
              label.innerText = 'מזהה רשימת תפוצה:';
              inputArea.placeholder = 'הכנס מספר מזהה בלבד';
              excelGroup.style.display = 'none';
          } else {
              label.innerText = 'מזהה רשימת צינתוקים:';
              inputArea.placeholder = 'הכנס מספר מזהה בלבד';
              excelGroup.style.display = 'none';
          }
      }
      
      document.getElementById('excelFile').addEventListener('change', function(e) {
          const file = e.target.files[0];
          const reader = new FileReader();
          reader.onload = function(event) {
              try {
                  const data = new Uint8Array(event.target.result);
                  const workbook = XLSX.read(data, { type: 'array' });
                  const sheet = workbook.Sheets[workbook.SheetNames[0]];
                  const rows = XLSX.utils.sheet_to_json(sheet, { header: 1 });
                  const phones = rows.map(r => r[0]).filter(c => c);
                  document.getElementById('targetInput').value = phones.join('\n');
              } catch (err) { alert("שגיאה בקריאת הקובץ"); }
          };
          reader.readAsArrayBuffer(file);
      });
      
      async function sendCampaign() {
          const btn = document.getElementById('submitBtn');
          const errorDiv = document.getElementById('error-display');
          errorDiv.style.display = "none";
          btn.innerText = "שולח... נא להמתין";
          btn.disabled = true;
      
          const token = document.getElementById('token').value.trim();
          const userInput = document.getElementById('targetInput').value.trim();
          let ivrPath = document.getElementById('ivrPath').value.trim();
          const timeout = document.getElementById('callsTimeOut').value;
          const callerId = document.getElementById('callerId').value.trim();
          const targetType = document.querySelector('input[name="targetType"]:checked').value;
      
          if (!token || !userInput || !ivrPath) {
              showError("חובה למלא את כל השדות");
              resetBtn();
              return;
          }
      
          // בניית פרמטר phones עם הקידומת המתאימה מאחורי הקלעים
          let phonesParam = "";
          if (targetType === 'tpl') {
              phonesParam = `tpl:${userInput}`;
          } else if (targetType === 'tzl') {
              phonesParam = `tzl:${userInput}`;
          } else {
              phonesParam = userInput.split('\n').map(p => p.trim()).filter(p => p).join(':');
          }
      
          if (!ivrPath.startsWith('/')) ivrPath = '/' + ivrPath;
          const finalIvrPath = `ivr2:${ivrPath}`;
      
          let url = `https://www.call2all.co.il/ym/api/CallExtensionBridging?token=${token}&phones=${phonesParam}&ivrPath=${finalIvrPath}&callsTimeOut=${timeout}`;
          if (callerId) url += `&callerId=${callerId}`;
      
          try {
              const response = await fetch(url);
              const result = await response.json();
              if (result.responseStatus === "OK") {
                  showSuccess(result);
              } else {
                  showError("שגיאת מערכת: " + (result.message || "שגיאה"));
              }
          } catch (e) {
              showError("שגיאת תקשורת.");
          } finally {
              resetBtn();
          }
      }
      
      function showSuccess(data) {
          const table = document.getElementById('resultTable');
          table.innerHTML = `<tr><td>סטטוס</td><td>${data.responseStatus}</td></tr>
                             <tr><td>מזהה קמפיין</td><td>${data.campaignId || 'אין'}</td></tr>
                             <tr><td>מספרים שנקלטו</td><td>${data.callsCount || '0'}</td></tr>`;
          document.getElementById('successModal').style.display = "block";
      }
      
      function showError(msg) {
          const errorDiv = document.getElementById('error-display');
          errorDiv.innerText = msg;
          errorDiv.style.display = "block";
      }
      
      function resetBtn() {
          const btn = document.getElementById('submitBtn');
          btn.innerText = "שיגור קמפיין";
          btn.disabled = false;
      }
      
      function closeModal() { document.getElementById('successModal').style.display = "none"; }
      

      </script>

      </body>
      </html>

      קרדיט: @אA

      א תגובה 1 תגובה אחרונה תגובה ציטוט 1
      • א
        אאא יוני @אA נערך לאחרונה על ידי

        @אA כתב בקבצי HTML לשימוש במערכות ימות המשיח:

        הפעלת קמפיין - הנכנס לשלוחה במערכת.html

        מה הכוונה?
        "הנכנס לשולחה במערכת"?שליחת קמפיין רגיל? משהו אחר?
        (סליחה על ההתערבות בשירשור בלנ"ד אח"כ אמחק )

        תגובה 1 תגובה אחרונה תגובה ציטוט 0
        • א
          אA נערך לאחרונה על ידי אA

          קובץ להוספת והגדרת שלוחות במערכות

          הקובץ מתעדכן מידי פעם.
          ניתן לעזור בשדרוג הקובץ כאן

          עידכון אחרון: א' טבת
          יצירת והגדרת שלוחות.html

          הקוד מצורף בספויילר

          <!DOCTYPE html>
          <html lang="he" dir="rtl">
          <head>
          <meta charset="UTF-8">
          <title>ממשק יצירת והגדרת שלוחות - מתוקן</title>
          <style>
          :root { --primary: #3498db; --success: #2ecc71; --danger: #e74c3c; --dark: #2c3e50; --bg: #f4f7f6; }
          body { font-family: 'Segoe UI', sans-serif; background-color: var(--bg); margin: 0; padding: 20px; direction: rtl; }
          .container { max-width: 800px; margin: auto; background: white; border-radius: 12px; box-shadow: 0 8px 30px rgba(0,0,0,0.1); overflow: hidden; }
          .header { background: var(--dark); color: white; padding: 20px; text-align: center; }
          .content { padding: 30px; position: relative; }
          .card { border: 1px solid #ddd; padding: 20px; border-radius: 8px; margin-bottom: 20px; background: #fff; position: relative; }
          label { display: block; margin-bottom: 6px; font-weight: bold; }
          input, select { width: 100%; padding: 12px; border: 1px solid #ccc; border-radius: 6px; box-sizing: border-box; font-size: 16px; margin-bottom: 10px; }

              .toolbar { display: flex; justify-content: space-between; gap: 10px; margin-bottom: 15px; }
              .btn-small { padding: 8px 15px; font-size: 14px; cursor: pointer; border-radius: 6px; border: 1px solid var(--dark); background: white; }
          
              .btn { padding: 12px; border-radius: 6px; border: none; font-weight: bold; cursor: pointer; width: 100%; transition: 0.2s; font-size: 16px; }
              .btn-primary { background: var(--primary); color: white; }
              .btn-success { background: var(--success); color: white; }
              .btn-danger { background: var(--danger); color: white; }
              
              #wizard-box { text-align: center; border: 2px solid var(--primary); display: none; }
              #display-q { font-size: 22px; font-weight: bold; margin-bottom: 20px; color: var(--dark); min-height: 50px; }
              .choice-btns { display: flex; gap: 15px; justify-content: center; }
              
              .token-dropdown {
                  position: absolute; width: calc(100% - 20px); background: white; border: 1px solid #ddd;
                  border-radius: 6px; box-shadow: 0 4px 10px rgba(0,0,0,0.1); z-index: 100;
                  max-height: 200px; overflow-y: auto; display: none;
              }
              .token-item { padding: 10px; cursor: pointer; border-bottom: 1px solid #eee; display: flex; justify-content: space-between; }
              .token-item:hover { background: #f0f8ff; }
          </style>
          

          </head>
          <body>

          <div class="container">
          <div class="header"><h1>ממשק יצירת והגדרת שלוחות</h1></div>

          <div class="content">
              <div class="toolbar">
                  <button class="btn-small" onclick="exportDatabase()">📥 הורדת גיבוי JSON</button>
                  <button class="btn-small" onclick="document.getElementById('json-upload').click()">📁 ייבוא מאגר JSON</button>
                  <input type="file" id="json-upload" accept=".json" style="display:none" onchange="handleJsonImport(this)">
              </div>
          
              <div id="setup-card" class="card">
                  <div style="display:flex; gap:10px;">
                      <div style="flex:2; position: relative;">
                          <label>טוקן:</label>
                          <input type="text" id="api-token" placeholder="הזן טוקן או בחר מרשימה" onfocus="showTokenList()">
                          <div id="token-list" class="token-dropdown"></div>
                      </div>
                      <div style="flex:1;">
                          <label>מספר שלוחה:</label>
                          <input type="text" id="api-path" placeholder="למשל: 1/5">
                      </div>
                  </div>
          
                  <label>בחר סוג שלוחה:</label>
                  <select id="run-main-select"></select>
                  
                  <button id="start-btn" class="btn btn-primary" onclick="initWizard()">התחל שאלון הגדרות</button>
              </div>
          
              <div id="wizard-box" class="card">
                  <div id="display-q">טוען שאלה...</div>
                  
                  <div id="sub-input-box" style="display:none; margin-bottom:20px;">
                      <p id="sub-q-label" style="font-weight:bold;"></p>
                      <input type="text" id="user-sub-val" placeholder="הכנס ערך כאן...">
                      <button class="btn btn-primary" onclick="handleSubInput()">אישור והמשך</button>
                  </div>
          
                  <div id="choice-btns" class="choice-btns">
                      <button class="btn btn-success" style="width:120px;" onclick="processChoice(true)">כן</button>
                      <button class="btn btn-danger" style="width:120px;" onclick="processChoice(false)">לא</button>
                  </div>
              </div>
          
              <div id="final-box" class="card" style="display:none; text-align:center;">
                  <h3>הגדרות מוכנות:</h3>
                  <div id="final-string" style="background:#eee; padding:10px; margin:10px 0; word-break:break-all; font-family:monospace;"></div>
                  <button class="btn btn-success" onclick="sendToYemot()">🚀 שלח לימות המשיח</button>
                  <button class="btn" style="margin-top:10px;" onclick="location.reload()">ביטול</button>
              </div>
          </div>
          

          </div>

          <script>
          // מאגר ברירת מחדל אם אין כלום בזיכרון
          const DEFAULT_DATA = {
          "type=menu": [
          { "q": "האם להפעיל השמעת תפריט?", "v": "say_menu=yes", "hasSub": false },
          { "q": "האם להגדיר כותרת לשלוחה?", "v": "title=[VALUE]", "hasSub": true, "subQ": "מה הכותרת?", "subKey": "[VALUE]" }
          ],
          "type=playfile": [
          { "q": "האם לאפשר דילוג על קבצים?", "v": "playfile_control=yes", "hasSub": false }
          ]
          };

          let DATABASE_CONTENT = JSON.parse(localStorage.getItem('yemot_db')) || DEFAULT_DATA;
          let currentMainDef = "";
          let currentStep = 0;
          let finalParams = [];
          
          window.onload = () => { updateDropdown(); renderTokenList(); };
          
          // --- ייבוא / ייצוא ---
          function exportDatabase() {
              const blob = new Blob([JSON.stringify(DATABASE_CONTENT, null, 2)], { type: 'application/json' });
              const a = document.createElement('a');
              a.href = URL.createObjectURL(blob);
              a.download = 'yemot_db.json';
              a.click();
          }
          
          function handleJsonImport(input) {
              const file = input.files[0];
              if (!file) return;
              const reader = new FileReader();
              reader.onload = function(e) {
                  try {
                      const imported = JSON.parse(e.target.result);
                      DATABASE_CONTENT = imported;
                      localStorage.setItem('yemot_db', JSON.stringify(DATABASE_CONTENT));
                      updateDropdown();
                      alert("המאגר עודכן בהצלחה!");
                  } catch(err) { alert("קובץ לא תקין"); }
              };
              reader.readAsText(file);
          }
          
          // --- לוגיקת שאלון (התיקון כאן) ---
          function updateDropdown() {
              const select = document.getElementById('run-main-select');
              select.innerHTML = '<option value="">-- בחר --</option>';
              Object.keys(DATABASE_CONTENT).forEach(key => {
                  const opt = document.createElement('option');
                  opt.value = key; opt.innerText = key;
                  select.appendChild(opt);
              });
          }
          
          function initWizard() {
              currentMainDef = document.getElementById('run-main-select').value;
              if(!currentMainDef) return alert("אנא בחר סוג שלוחה");
          
              currentStep = 0;
              finalParams = [currentMainDef]; // מתחיל עם סוג השלוחה (למשל type=menu)
              
              document.getElementById('setup-card').style.display = 'none';
              document.getElementById('wizard-box').style.display = 'block';
              
              renderStep();
          }
          
          function renderStep() {
              const questions = DATABASE_CONTENT[currentMainDef];
              
              // בדיקה אם סיימנו את כל השאלות במאגר
              if(!questions || currentStep >= questions.length) {
                  showFinal();
                  return;
              }
          
              const currentItem = questions[currentStep];
              document.getElementById('display-q').innerText = currentItem.q;
              document.getElementById('choice-btns').style.display = 'flex';
              document.getElementById('sub-input-box').style.display = 'none';
          }
          
          function processChoice(isYes) {
              const item = DATABASE_CONTENT[currentMainDef][currentStep];
              if(isYes) {
                  if(item.hasSub) {
                      // מעבר להזנת ערך ידני
                      document.getElementById('choice-btns').style.display = 'none';
                      document.getElementById('sub-input-box').style.display = 'block';
                      document.getElementById('sub-q-label').innerText = item.subQ;
                  } else {
                      finalParams.push(item.v);
                      currentStep++;
                      renderStep();
                  }
              } else {
                  currentStep++;
                  renderStep();
              }
          }
          
          function handleSubInput() {
              const item = DATABASE_CONTENT[currentMainDef][currentStep];
              const val = document.getElementById('user-sub-val').value.trim();
              if(!val) return alert("חובה להזין ערך");
          
              // החלפת ה-Placeholder בערך שהמשתמש הזין
              const formattedVal = item.v.replace(item.subKey, val);
              finalParams.push(formattedVal);
              
              document.getElementById('user-sub-val').value = '';
              currentStep++;
              renderStep();
          }
          
          function showFinal() {
              document.getElementById('wizard-box').style.display = 'none';
              document.getElementById('final-box').style.display = 'block';
              document.getElementById('final-string').innerText = finalParams.join('&');
          }
          
          // --- טוקנים ו-API ---
          function showTokenList() { document.getElementById('token-list').style.display = 'block'; }
          function selectToken(t) { 
              document.getElementById('api-token').value = t; 
              document.getElementById('token-list').style.display = 'none';
          }
          function renderTokenList() {
              const saved = JSON.parse(localStorage.getItem('saved_yemot_tokens')) || [];
              const list = document.getElementById('token-list');
              list.innerHTML = saved.map(i => `<div class="token-item" onclick="selectToken('${i.token}')"><span>${i.alias}</span></div>`).join('');
          }
          
          async function sendToYemot() {
              const token = document.getElementById('api-token').value;
              const path = document.getElementById('api-path').value;
              const url = `https://www.call2all.co.il/ym/api/UpdateExtension?token=${token}&path=ivr2:${path}&${finalParams.join('&')}`;
              try {
                  const r = await fetch(url);
                  const txt = await r.text();
                  alert("תשובה מימות: " + txt);
              } catch(e) { alert("שגיאת תקשורת"); }
          }
          

          </script>
          </body>
          </html>

          קרדיט: @אA

          פ תגובה 1 תגובה אחרונה תגובה ציטוט 0
          • H
            haiims @אA נערך לאחרונה על ידי haiims

            @אA במערכת מעלה קבצים יש אפשרות לעלות לכמה שלוחות יחד? למחוק קבצים אפשר?
            ואין אפשרות לראות % או משהו כזה עד לסיום הפעולה ?

            תגובה 1 תגובה אחרונה תגובה ציטוט 0
            • פ
              פיתה @אA נערך לאחרונה על ידי

              פוסט זה נמחק!
              א תגובה 1 תגובה אחרונה תגובה ציטוט 0
              • א
                אA @פיתה נערך לאחרונה על ידי

                פוסט זה נמחק!
                תגובה 1 תגובה אחרונה תגובה ציטוט 0
                • א
                  אA נערך לאחרונה על ידי אA

                  ממשק ניהול הקבצים במערכת

                  ממשק ניהול קבצים במערכת.html

                  הקוד מצורף בספויילר

                  <!DOCTYPE html>
                  <html lang="he" dir="rtl">
                  <head>
                  <meta charset="UTF-8">
                  <title>ניהול שלוחות ימות המשיח</title>
                  <style>
                  :root {
                  --primary: #2c3e50; --accent: #3498db; --success: #27ae60;
                  --danger: #e74c3c; --violet: #8e44ad; --orange: #f39c12;
                  }
                  body { font-family: 'Segoe UI', sans-serif; background: #f4f7f6; margin: 0; padding: 20px; }

                      /* סרגל עליון */
                      .top-bar { 
                          background: white; padding: 15px; border-radius: 10px; 
                          box-shadow: 0 2px 10px rgba(0,0,0,0.05); display: flex; 
                          flex-direction: column; gap: 10px; margin-bottom: 20px; 
                      }
                      .inputs-row { display: flex; gap: 10px; align-items: center; width: 100%; }
                      input { padding: 8px; border: 1px solid #ddd; border-radius: 5px; flex: 1; }
                  
                      /* עיצוב רכיב הטוקנים */
                      .token-main { position: relative; flex: 1; display: flex; } /* גודל זהה לשדה הנתיב */
                      #tokenField { flex: 1; width: 100%; }
                      
                      .token-dropdown { 
                          position: absolute; width: 100%; background: white; border: 1px solid #ccc; 
                          border-radius: 8px; box-shadow: 0 4px 10px rgba(0,0,0,0.1); 
                          z-index: 1000; max-height: 250px; overflow-y: auto; display: none; top: 100%;
                      }
                      .token-item { 
                          display: flex; justify-content: space-between; align-items: center; 
                          padding: 10px; cursor: pointer; border-bottom: 1px solid #eee; color: #333;
                      }
                      .token-item:hover { background: #f8f9fa; }
                      .delete-item { color: #dc3545; font-weight: bold; padding: 5px 10px; cursor: pointer; border: none; background: none; }
                      .dropdown-footer { padding: 8px; background: #f1f3f5; display: flex; gap: 5px; justify-content: center; border-top: 1px solid #ddd; }
                      .footer-btn { font-size: 11px; padding: 4px 8px; cursor: pointer; border: 1px solid #ccc; background: white; border-radius: 4px; }
                      
                      /* כפתורים וטבלה */
                      .btn { cursor: pointer; border: none; border-radius: 4px; padding: 4px 8px; font-weight: bold; color: white; transition: 0.2s; font-size: 11px; text-align: center; display: inline-block; width: 100%; max-width: 75px; }
                      .btn:hover { opacity: 0.85; transform: translateY(-1px); }
                      .btn-load { background: var(--primary); padding: 8px 18px; width: auto; max-width: none; font-size: 14px; }
                      
                      .ext-container { background: #fff; padding: 15px; border-radius: 10px; box-shadow: 0 2px 10px rgba(0,0,0,0.05); margin-bottom: 20px; border-top: 4px solid var(--primary); }
                      .ext-container h4 { margin: 0 0 10px 0; color: var(--primary); display: flex; justify-content: space-between; align-items: center; }
                      #extTextArea { width: 100%; height: 120px; font-family: 'Consolas', monospace; font-size: 13px; padding: 10px; box-sizing: border-box; border: 1px solid #ddd; background: #fcfcfc; border-radius: 5px; }
                  
                      table { width: 100%; background: white; border-collapse: collapse; border-radius: 8px; overflow: hidden; }
                      th { background: #f8f9fa; padding: 10px; font-size: 12px; border-bottom: 2px solid #eee; }
                      td { padding: 5px 8px; border-bottom: 1px solid #eee; text-align: center; font-size: 12px; }
                      
                      .dl { background: var(--success); } .ed { background: var(--orange); } .up { background: var(--accent); } .del { background: var(--danger); } .view { background: var(--violet); }
                  
                      .modal { display: none; position: fixed; inset: 0; background: rgba(0,0,0,0.6); justify-content: center; align-items: center; z-index: 1000; }
                      .modal-content { background: white; padding: 25px; border-radius: 12px; width: 600px; max-width: 95%; }
                      .modal-footer { margin-top: 20px; display: flex; justify-content: flex-start; flex-direction: row-reverse; gap: 10px; }
                      .convert-row { display: flex; gap: 10px; justify-content: center; margin-top: 20px; }
                  </style>
                  

                  </head>
                  <body>

                  <div class="top-bar">
                  <div class="inputs-row">
                  <div class="token-main">
                  <input type="text" id="tokenField" placeholder="הזן טוקן או בחר"
                  onclick="toggleDropdown(true)" oninput="filterDropdown(this.value)" onkeypress="handleEnter(event)" autocomplete="off">
                  <div id="tokenDropdown" class="token-dropdown"></div>
                  </div>

                      <input type="text" id="pathField" value="" placeholder="נתיב שלוחה" onkeypress="handleEnter(event)">
                      <button class="btn btn-load" onclick="startProcess()">טען רשימת קבצים</button>
                  </div>
                  
                  <div style="display: flex; align-items: center; gap: 15px; padding-top: 5px;">
                      <div style="display: flex; align-items: center; gap: 5px;">
                          <input type="checkbox" id="saveTokenToggle" style="width: auto; cursor: pointer;" 
                                 onchange="document.getElementById('tokenNameField').style.display = this.checked ? 'block' : 'none'">
                          <label for="saveTokenToggle" style="font-size: 12px; cursor: pointer; color: #666;">שמור טוקן זה במאגר</label>
                      </div>
                      <div id="tokenNameField" style="display:none;">
                          <input type="text" id="tokenAlias" placeholder="שם למזהה (למשל: המערכת שלי)" style="font-size: 12px; padding: 5px; width: 200px;">
                      </div>
                  </div>
                  

                  </div>

                  <div class="ext-container" id="extContainer" style="display:none;">
                  <h4>
                  <span>הגדרות שלוחה (ext.ini)</span>
                  <div style="display:flex; gap:8px;">
                  <button class="btn" style="background:var(--orange); width:auto; padding:5px 15px;" onclick="renameExtIni()">שנה שם</button>
                  <button class="btn" style="background:var(--success); width:auto; padding:5px 15px;" onclick="saveExtIni()">שמור שינויים</button>
                  </div>
                  </h4>
                  <textarea id="extTextArea"></textarea>
                  </div>

                  <table>
                  <thead>
                  <tr>
                  <th style="text-align: right; width: 25%;">שם קובץ</th>
                  <th>גודל</th>
                  <th>תצוגה</th>
                  <th>הורדה</th>
                  <th>שינוי שם</th>
                  <th>החלפה</th>
                  <th>מחיקה</th>
                  </tr>
                  </thead>
                  <tbody id="tableBody"></tbody>
                  </table>

                  <div id="mainModal" class="modal">
                  <div class="modal-content">
                  <h3 id="modalTitle" style="margin:0 0 15px 0; border-bottom:1px solid #eee; padding-bottom:10px;"></h3>
                  <div id="modalBody"></div>
                  <div class="modal-footer" id="modalFooter">
                  <button id="saveBtn" class="btn btn-load">שמור</button>
                  <button class="btn" onclick="closeModal()" style="background:#95a5a6;">ביטול</button>
                  </div>
                  </div>
                  </div>

                  <script>
                  const API_BASE = 'https://www.call2all.co.il/ym/api/';
                  const STORAGE_KEY = 'yemot_permanent_storage';
                  let savedTokens = JSON.parse(localStorage.getItem(STORAGE_KEY) || '{}');

                  document.addEventListener('click', (e) => { if (!e.target.closest('.token-main')) toggleDropdown(false); });
                  function toggleDropdown(show) {
                      const dropdown = document.getElementById('tokenDropdown');
                      if (show) { renderDropdown(); dropdown.style.display = 'block'; }
                      else { dropdown.style.display = 'none'; }
                  }
                  function renderDropdown(filter = "") {
                      const dropdown = document.getElementById('tokenDropdown');
                      dropdown.innerHTML = '';
                      const filteredKeys = Object.keys(savedTokens).filter(a => a.toLowerCase().includes(filter.toLowerCase()));
                      filteredKeys.forEach(alias => {
                          const item = document.createElement('div');
                          item.className = 'token-item';
                          item.innerHTML = `<span>${alias}</span><button type="button" class="delete-item">✖</button>`;
                          item.onclick = () => { document.getElementById('tokenField').value = savedTokens[alias]; toggleDropdown(false); };
                          item.querySelector('.delete-item').onclick = (e) => {
                              e.stopPropagation();
                              if(confirm(`למחוק את ${alias}?`)) { 
                                  delete savedTokens[alias]; 
                                  localStorage.setItem(STORAGE_KEY, JSON.stringify(savedTokens)); 
                                  renderDropdown(filter); 
                              }
                          };
                          dropdown.appendChild(item);
                      });
                      const footer = document.createElement('div');
                      footer.className = 'dropdown-footer';
                      footer.innerHTML = `<button type="button" class="footer-btn" style="color:red" onclick="if(confirm('למחוק הכל?')){savedTokens={};localStorage.setItem(STORAGE_KEY,'{}');renderDropdown();}">מחק הכל</button>`;
                      footer.onclick = (e) => e.stopPropagation();
                      dropdown.appendChild(footer);
                  }
                  function filterDropdown(val) { renderDropdown(val); document.getElementById('tokenDropdown').style.display = 'block'; }
                  
                  function startProcess() {
                      saveCurrentTokenIfRequested();
                      loadDirectory();
                  }
                  
                  function saveCurrentTokenIfRequested() {
                      const token = document.getElementById('tokenField').value.trim();
                      const alias = document.getElementById('tokenAlias').value.trim();
                      if (document.getElementById('saveTokenToggle').checked && alias && token) {
                          savedTokens[alias] = token;
                          localStorage.setItem(STORAGE_KEY, JSON.stringify(savedTokens));
                      }
                  }
                  
                  function handleEnter(event) { if (event.key === "Enter") startProcess(); }
                  
                  function getFullPath(fileName = "") {
                      let rawPath = document.getElementById('pathField').value.trim();
                      if (rawPath && !rawPath.endsWith('/') && fileName !== "") rawPath += '/';
                      return `ivr2:${rawPath}${fileName}`;
                  }
                  
                  async function callApi(method, params = {}) {
                      const token = document.getElementById('tokenField').value.trim();
                      if (!token) return;
                      let url = `${API_BASE}${method}?token=${token}`;
                      for (let key in params) url += `&${key}=${encodeURIComponent(params[key])}`;
                      const res = await fetch(url);
                      return await res.json();
                  }
                  
                  async function loadDirectory() {
                      const data = await callApi('GetIVR2Dir', { path: getFullPath() });
                      const body = document.getElementById('tableBody');
                      body.innerHTML = '';
                      if (data && data.files) {
                          data.files.forEach(file => {
                              const isText = file.name.endsWith('.ini') || file.name.endsWith('.tts');
                              body.innerHTML += `
                                  <tr>
                                      <td style="text-align: right;"><strong>${file.name}</strong></td>
                                      <td style="color:#888;">${file.size} B</td>
                                      <td>${isText ? `<button class="btn view" onclick="openTextFile('${file.name}')">הצג</button>` : '-'}</td>
                                      <td><button class="btn dl" onclick="handleDownloadClick('${file.name}')">הורדה</button></td>
                                      <td><button class="btn ed" onclick="renameFile('${file.name}')">שינוי</button></td>
                                      <td><button class="btn up" onclick="uploadUI('${file.name}')">החלפה</button></td>
                                      <td><button class="btn del" onclick="deleteFile('${file.name}')">מחיקה</button></td>
                                  </tr>`;
                          });
                          loadExtIni();
                      }
                  }
                  
                  async function loadExtIni() {
                      const data = await callApi('GetTextFile', { what: getFullPath('ext.ini') });
                      document.getElementById('extContainer').style.display = 'block';
                      document.getElementById('extTextArea').value = (data && data.exists !== false) ? data.contents || "" : "קובץ ext.ini לא נמצא.";
                  }
                  
                  async function saveExtIni() {
                      const res = await callApi('UploadTextFile', { what: getFullPath('ext.ini'), contents: document.getElementById('extTextArea').value });
                      if (res && res.responseStatus === "OK") alert("נשמר!");
                  }
                  
                  async function renameExtIni() {
                      const newName = prompt("שם חדש ל-ext.ini:", "ext.ini");
                      if (newName) {
                          const res = await callApi('FileAction', { action: 'move', what: getFullPath('ext.ini'), target: getFullPath(newName) });
                          if (res && res.responseStatus === "OK") loadDirectory();
                      }
                  }
                  
                  function handleDownloadClick(name) {
                      if (name.toLowerCase().endsWith('.ymgr')) showConvertModal(name);
                      else window.open(`${API_BASE}DownloadFile?token=${document.getElementById('tokenField').value}&path=${getFullPath(name)}`);
                  }
                  
                  function showConvertModal(name) {
                      const html = `
                          <p style="text-align:center;">בחר פורמט המרה עבור קובץ הנתונים:</p>
                          <div class="convert-row">
                              <button class="btn" style="background:var(--primary); max-width:none; flex:1; padding:10px;" onclick="executeRender('${name}', '')">ללא המרה</button>
                              <button class="btn" style="background:var(--success); max-width:none; flex:1; padding:10px;" onclick="executeRender('${name}', 'csv')">אקסל (CSV)</button>
                              <button class="btn" style="background:var(--violet); max-width:none; flex:1; padding:10px;" onclick="executeRender('${name}', 'html')">דף HTML</button>
                          </div>`;
                      showModal("המרה והורדה", html);
                      document.getElementById('modalFooter').style.display = 'none';
                  }
                  
                  function executeRender(name, type) {
                      const token = document.getElementById('tokenField').value;
                      const url = type === "" ? 
                          `${API_BASE}DownloadFile?token=${token}&path=${getFullPath(name)}` : 
                          `${API_BASE}RenderYMGRFile?token=${token}&wath=${getFullPath(name)}&convertType=${type}`;
                      window.open(url);
                      closeModal();
                  }
                  
                  function showModal(title, html) {
                      document.getElementById('modalTitle').innerText = title;
                      document.getElementById('modalBody').innerHTML = html;
                      document.getElementById('mainModal').style.display = 'flex';
                      document.getElementById('modalFooter').style.display = 'flex';
                  }
                  function closeModal() { document.getElementById('mainModal').style.display = 'none'; }
                  
                  async function deleteFile(name) { if (confirm(`למחוק את ${name}?`)) { const res = await callApi('FileAction', { action: 'delete', what: getFullPath(name) }); if (res.responseStatus === "OK") loadDirectory(); } }
                  function renameFile(name) { const newName = prompt("שם חדש:", name); if (newName) callApi('FileAction', { action: 'move', what: getFullPath(name), target: getFullPath(newName) }).then(loadDirectory); }
                  async function openTextFile(name) {
                      const data = await callApi('GetTextFile', { what: getFullPath(name) });
                      showModal(`עריכת ${name}`, `<textarea id="modalTextArea" style="width:100%; height:300px; font-family:monospace;">${data.contents || ''}</textarea>`);
                      document.getElementById('saveBtn').onclick = async () => { await callApi('UploadTextFile', { what: getFullPath(name), contents: document.getElementById('modalTextArea').value }); closeModal(); loadDirectory(); };
                  }
                  function uploadUI(name) {
                      showModal(`החלפת ${name}`, `<input type="file" id="fInp" style="margin-top:10px;">`);
                      document.getElementById('saveBtn').onclick = async () => {
                          const token = document.getElementById('tokenField').value;
                          const file = document.getElementById('fInp').files[0];
                          if (!file) return;
                          const fd = new FormData(); fd.append('file', file);
                          await fetch(`${API_BASE}UploadFile?token=${token}&path=${getFullPath()}`, { method: 'POST', body: fd });
                          closeModal(); loadDirectory();
                      };
                  }
                  

                  </script>
                  </body>
                  </html>

                  קרדיט: @אA

                  תגובה 1 תגובה אחרונה תגובה ציטוט 1
                  • ע
                    עידו נערך לאחרונה על ידי

                    פוסט זה נמחק!
                    תגובה 1 תגובה אחרונה תגובה ציטוט 0
                    • א
                      אA נערך לאחרונה על ידי

                      ממשק ליצירת ניהול והפעלת קמפיין

                      לא בדקתי את הפעולה שלו בזמן אמת, אשמח אם יש מי שהשתמש בזה שיעדכן.

                      הקוד מצורף בספויילר

                      <!DOCTYPE html>
                      <html lang="he" dir="rtl">
                      <head>
                      <meta charset="UTF-8">
                      <title>מערכת ניהול קמפיינים - Yemot API</title>
                      <style>
                      :root {
                      --primary-color: #2c3e50;
                      --accent-color: #3498db;
                      --bg-color: #f8f9fa;
                      }
                      body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; background-color: var(--bg-color); margin: 0; padding: 20px; }
                      .container { max-width: 1100px; margin: auto; background: white; border-radius: 12px; box-shadow: 0 4px 15px rgba(0,0,0,0.1); overflow: hidden; }

                          /* תפריט עליון */
                          .tabs { display: flex; background: var(--primary-color); padding: 0 10px; }
                          .tab-button { 
                              padding: 15px 25px; border: none; background: none; color: white; 
                              cursor: pointer; font-size: 16px; transition: 0.3s; border-bottom: 3px solid transparent;
                          }
                          .tab-button:hover { background: rgba(255,255,255,0.1); }
                          .tab-button.active { border-bottom: 3px solid var(--accent-color); font-weight: bold; }
                      
                          /* תוכן החלונות */
                          .tab-content { display: none; padding: 30px; animation: fadeIn 0.4s; }
                          .tab-content.active { display: block; }
                      
                          @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
                      
                          .form-group { margin-bottom: 20px; }
                          label { display: block; margin-bottom: 8px; font-weight: 600; color: #444; }
                          input, select, textarea { 
                              width: 100%; padding: 12px; border: 1px solid #ddd; border-radius: 6px; 
                              font-size: 14px; box-sizing: border-box;
                          }
                          .btn-row { display: flex; gap: 10px; margin-top: 20px; }
                          button { 
                              padding: 12px 24px; border: none; border-radius: 6px; cursor: pointer; 
                              font-weight: bold; transition: 0.2s;
                          }
                          .btn-primary { background: var(--accent-color); color: white; }
                          .btn-danger { background: #e74c3c; color: white; }
                          .btn-success { background: #27ae60; color: white; }
                          
                          .response-area { 
                              margin-top: 25px; padding: 15px; background: #272c33; color: #61dafb; 
                              border-radius: 6px; font-family: monospace; font-size: 13px; white-space: pre-wrap;
                              max-height: 250px; overflow-y: auto; direction: ltr; text-align: left;
                          }
                          .info-box { background: #e8f4fd; padding: 15px; border-radius: 6px; border-right: 4px solid var(--accent-color); margin-bottom: 20px; }
                      </style>
                      

                      </head>
                      <body>

                      <div class="container">
                      <div style="background: #eee; padding: 15px 30px; border-bottom: 1px solid #ddd; display: flex; align-items: center; gap: 15px;">
                      <label style="margin:0;">טוקן גישה (token):</label>
                      <input type="text" id="mainToken" placeholder="הכנס טוקן API כאן" style="width: 350px;">
                      </div>

                      <nav class="tabs">
                          <button class="tab-button active" onclick="openTab(event, 'setup')">הקמה והגדרות</button>
                          <button class="tab-button" onclick="openTab(event, 'run')">הפעלת קמפיין</button>
                          <button class="tab-button" onclick="openTab(event, 'contacts')">ניהול מספרים</button>
                          <button class="tab-button" onclick="openTab(event, 'monitor')">בקרה בזמן אמת</button>
                          <button class="tab-button" onclick="openTab(event, 'schedule')">תזמון</button>
                      </nav>
                      
                      <div id="setup" class="tab-content active">
                          <h2>הקמת תבנית קמפיין חדשה</h2>
                          <div class="form-group">
                              <label>שם הקמפיין (תיאור):</label>
                              <input type="text" id="setup_desc" placeholder="לדוגמה: קמפיין התרמה">
                          </div>
                          <button class="btn-primary" onclick="executeCall('CreateTemplate', {description: 'setup_desc'})">צור תבנית חדשה</button>
                          <div class="response-area" id="res-setup">// ממתין לפעולה...</div>
                      </div>
                      
                      <div id="run" class="tab-content">
                          <h2>הפעלת קמפיין</h2>
                          <div class="form-group">
                              <label>מזהה תבנית:</label>
                              <input type="number" id="run_tpl">
                          </div>
                          <div class="form-group">
                              <label>רשימת מספרים - הפרדה בנקודותיים:</label>
                              <textarea id="run_phones" rows="3" placeholder="0501234567:0507654321"></textarea>
                          </div>
                          <button class="btn-success" onclick="executeCall('RunCampaign', {templateId: 'run_tpl', phones: 'run_phones'})">שגר קמפיין עכשיו</button>
                          <div class="response-area" id="res-run">// ממתין לפעולה...</div>
                      </div>
                      
                      <div id="contacts" class="tab-content">
                          <h2>ניהול רשימות תפוצה</h2>
                          <div class="form-group">
                              <label>מזהה תבנית:</label>
                              <input type="number" id="list_tpl">
                          </div>
                          <div class="form-group">
                              <label>נתוני טלפונים:</label>
                              <textarea id="list_data" rows="5" placeholder="0501112233,ישראל ישראלי"></textarea>
                          </div>
                          <div class="btn-row">
                              <button class="btn-primary" onclick="executeCall('UploadPhoneList', {templateId: 'list_tpl', data: 'list_data'})">העלה רשימה</button>
                              <button class="btn-danger" onclick="executeCall('ClearTemplateEntries', {templateId: 'list_tpl'})">מחק את כל הרשימה</button>
                          </div>
                          <div class="response-area" id="res-contacts">// ממתין לפעולה...</div>
                      </div>
                      
                      <div id="monitor" class="tab-content">
                          <h2>ניהול קמפיין פעיל</h2>
                          <div class="form-group">
                              <label>מזהה קמפיין רץ:</label>
                              <input type="text" id="active_id">
                          </div>
                          <div class="btn-row">
                              <button class="btn-primary" onclick="executeCall('GetCampaignStatus', {campaignId: 'active_id'})">בדוק סטטוס</button>
                              <button class="btn-danger" onclick="executeCall('CampaignAction', {campaignId: 'active_id', action: 'stop'})">עצור קמפיין</button>
                              <button style="background: #f39c12; color:white;" onclick="executeCall('CampaignAction', {campaignId: 'active_id', action: 'setPaused'})">השהה או המשך</button>
                          </div>
                          <div class="response-area" id="res-monitor">// ממתין לפעולה...</div>
                      </div>
                      
                      <div id="schedule" class="tab-content">
                          <h2>תזמון קמפיין עתידי</h2>
                          <div class="form-group">
                              <label>מזהה תבנית:</label>
                              <input type="number" id="sched_tpl">
                          </div>
                          <div class="form-group">
                              <label>זמן לביצוע:</label>
                              <input type="text" id="sched_time" placeholder="yyyy-MM-dd HH:mm:ss">
                          </div>
                          <button class="btn-primary" onclick="executeCall('ScheduleCampaign', {templateId: 'sched_tpl', time: 'sched_time'})">קבע תזמון</button>
                          <div class="response-area" id="res-schedule">// ממתין לפעולה...</div>
                      </div>
                      

                      </div>

                      <script>
                      const API_BASE = "https://www.call2all.co.il/ym/api/";

                      function openTab(evt, tabName) {
                          var i, tabContent, tabButtons;
                          tabContent = document.getElementsByClassName("tab-content");
                          for (i = 0; i < tabContent.length; i++) tabContent[i].classList.remove("active");
                          tabButtons = document.getElementsByClassName("tab-button");
                          for (i = 0; i < tabButtons.length; i++) tabButtons[i].classList.remove("active");
                          document.getElementById(tabName).classList.add("active");
                          evt.currentTarget.classList.add("active");
                      }
                      
                      function executeCall(command, params) {
                          const token = document.getElementById('mainToken').value;
                          if(!token) { alert("חובה להזין טוקן!"); return; }
                      
                          let url = new URL(API_BASE + command);
                          url.searchParams.append("token", token);
                      
                          for (let key in params) {
                              let val = params[key];
                              let element = document.getElementById(val);
                              if(element) {
                                  url.searchParams.append(key, element.value);
                              } else {
                                  url.searchParams.append(key, val);
                              }
                          }
                      
                          const activeResArea = document.querySelector('.tab-content.active .response-area');
                          activeResArea.innerHTML = "שולח בקשה...\n\nURL:\n" + url.href;
                      }
                      

                      </script>

                      </body>
                      </html>

                      קרדיט: @אA

                      תגובה 1 תגובה אחרונה תגובה ציטוט 0
                      • א
                        אA נערך לאחרונה על ידי אA

                        הוספת טקסט למספר קבצים במערכת

                        הקוד מצורף בספויילר

                        <!DOCTYPE html>
                        <html lang="he" dir="rtl">
                        <head>
                            <meta charset="UTF-8">
                            <meta name="viewport" content="width=device-width, initial-scale=1.0">
                            <title>ניהול קבצים - ימות המשיח</title>
                            <style>
                                :root {
                                    --primary-color: #4a90e2;
                                    --secondary-color: #2ecc71;
                                    --danger-color: #e74c3c;
                                    --bg-color: #f4f7f6;
                                    --text-color: #333;
                                    --card-bg: #ffffff;
                                    --border-radius: 12px;
                                }
                        
                                body {
                                    font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
                                    background-color: var(--bg-color);
                                    color: var(--text-color);
                                    margin: 0;
                                    padding: 20px;
                                    display: flex;
                                    justify-content: center;
                                }
                        
                                .container {
                                    background-color: var(--card-bg);
                                    padding: 30px;
                                    border-radius: var(--border-radius);
                                    box-shadow: 0 10px 25px rgba(0,0,0,0.1);
                                    max-width: 650px;
                                    width: 100%;
                                }
                        
                                h2 {
                                    text-align: center;
                                    color: var(--primary-color);
                                    margin-bottom: 30px;
                                    font-weight: 600;
                                }
                        
                                .input-group {
                                    margin-bottom: 20px;
                                }
                        
                                label {
                                    display: block;
                                    margin-bottom: 8px;
                                    font-weight: bold;
                                    font-size: 0.9em;
                                }
                        
                                input[type="text"], textarea {
                                    width: 100%;
                                    padding: 12px;
                                    border: 2px solid #eee;
                                    border-radius: 8px;
                                    box-sizing: border-box;
                                    transition: border-color 0.3s;
                                    font-size: 16px;
                                }
                        
                                input[type="text"]:focus, textarea:focus {
                                    border-color: var(--primary-color);
                                    outline: none;
                                }
                        
                                .flex-row {
                                    display: flex;
                                    gap: 10px;
                                    align-items: center;
                                }
                        
                                button {
                                    padding: 12px 20px;
                                    border: none;
                                    border-radius: 8px;
                                    cursor: pointer;
                                    font-weight: bold;
                                    transition: all 0.3s;
                                    display: inline-flex;
                                    align-items: center;
                                    justify-content: center;
                                    white-space: nowrap;
                                }
                        
                                .btn-load {
                                    background-color: var(--primary-color);
                                    color: white;
                                    min-width: 120px;
                                }
                        
                                .btn-load:hover { background-color: #357abd; transform: translateY(-1px); }
                        
                                .btn-add {
                                    background-color: var(--secondary-color);
                                    color: white;
                                    font-size: 0.9em;
                                    gap: 8px;
                                }
                        
                                .btn-add:hover { background-color: #27ae60; }
                        
                                .btn-delete {
                                    background-color: var(--danger-color);
                                    color: white;
                                    padding: 10px;
                                    min-width: 40px;
                                }
                        
                                .btn-delete:hover { background-color: #c0392b; }
                        
                                .file-input-wrapper {
                                    display: flex;
                                    gap: 8px;
                                    margin-bottom: 10px;
                                    animation: fadeIn 0.3s ease;
                                }
                        
                                @keyframes fadeIn {
                                    from { opacity: 0; transform: translateY(10px); }
                                    to { opacity: 1; transform: translateY(0); }
                                }
                        
                                textarea {
                                    height: 180px;
                                    resize: vertical;
                                    background-color: #fafafa;
                                    font-family: monospace;
                                    margin-top: 10px;
                                }
                        
                                /* עיצוב חדש לאזור העלאת קובץ מקומי */
                                .file-upload-zone {
                                    margin: 15px 0;
                                    padding: 15px;
                                    border: 2px dashed #ccc;
                                    border-radius: 8px;
                                    text-align: center;
                                    background-color: #f9f9f9;
                                }
                        
                                .custom-file-upload {
                                    display: inline-block;
                                    padding: 8px 16px;
                                    cursor: pointer;
                                    background-color: #fff;
                                    border: 1px solid var(--primary-color);
                                    color: var(--primary-color);
                                    border-radius: 4px;
                                    font-weight: bold;
                                    transition: 0.3s;
                                }
                        
                                .custom-file-upload:hover {
                                    background-color: var(--primary-color);
                                    color: white;
                                }
                        
                                #localFileInput {
                                    display: none;
                                }
                        
                                .btn-upload {
                                    background-color: #e67e22;
                                    color: white;
                                    width: 100%;
                                    font-size: 1.1em;
                                    margin-top: 10px;
                                    box-shadow: 0 4px 15px rgba(230, 126, 34, 0.3);
                                }
                        
                                .btn-upload:hover { background-color: #d35400; }
                            </style>
                        </head>
                        <body>
                        
                        <div class="container">
                            <h2>ניהול קבצי מערכת</h2>
                        
                            <div class="input-group">
                                <label>טוקן אישי</label>
                                <input type="text" id="token" placeholder="הכנס את ה-Token שלך">
                            </div>
                        
                            <div class="input-group">
                                <label>מספר שלוחה</label>
                                <div class="flex-row">
                                    <input type="text" id="ext" placeholder="למשל: 1">
                                    <button class="btn-load" onclick="loadFirstFile()">טען תוכן מהשרת</button>
                                </div>
                            </div>
                        
                            <div class="input-group">
                                <label>שמות קבצים ליעד</label>
                                <div id="file-fields">
                                    <div class="file-input-wrapper">
                                        <input type="text" class="filename-input" placeholder="שם קובץ (למשל ext.ini)">
                                        <button class="btn-add" onclick="addNewFileField()">קובץ נוסף +</button>
                                    </div>
                                </div>
                            </div>
                        
                            <div class="input-group">
                                <label>תוכן הקובץ</label>
                                <textarea id="fileContents" placeholder="כאן יופיע תוכן הקובץ..."></textarea>
                                
                                <div class="file-upload-zone">
                                    <label for="localFileInput" class="custom-file-upload">
                                        📂 טען טקסט מקובץ במחשב
                                    </label>
                                    <input type="file" id="localFileInput" accept=".txt,.ini,.csv,.text" onchange="readLocalFile(this)">
                                    <div id="fileNameDisplay" style="margin-top: 8px; font-size: 0.8em; color: #666;"></div>
                                </div>
                            </div>
                        
                            <button class="btn-upload" onclick="uploadAll()">העלה קבצים למערכת</button>
                        </div>
                        
                        <script>
                            const baseUrl = 'https://www.call2all.co.il/ym/api/';
                        
                            // פונקציה לקריאת קובץ מקומי מהמחשב
                            function readLocalFile(input) {
                                const file = input.files[0];
                                if (!file) return;
                        
                                const reader = new FileReader();
                                document.getElementById('fileNameDisplay').innerText = "קובץ שנבחר: " + file.name;
                        
                                reader.onload = function(e) {
                                    document.getElementById('fileContents').value = e.target.result;
                                };
                        
                                reader.readAsText(file);
                            }
                        
                            function addNewFileField() {
                                const container = document.getElementById('file-fields');
                                const newDiv = document.createElement('div');
                                newDiv.className = 'file-input-wrapper';
                                newDiv.innerHTML = `
                                    <input type="text" class="filename-input" placeholder="שם קובץ נוסף">
                                    <button class="btn-delete" onclick="removeField(this)" title="מחק שדה">🗑️</button>
                                `;
                                container.appendChild(newDiv);
                            }
                        
                            function removeField(btn) {
                                btn.parentElement.remove();
                            }
                        
                            async function loadFirstFile() {
                                const token = document.getElementById('token').value;
                                const ext = document.getElementById('ext').value;
                                const firstInput = document.querySelector('.filename-input');
                                const fileName = firstInput ? firstInput.value : '';
                        
                                if (!token || !fileName) {
                                    alert("נא למלא טוקן ושם קובץ בתיבה הראשונה");
                                    return;
                                }
                        
                                const path = `ivr2:${ext}/${fileName}`;
                                try {
                                    const response = await fetch(`${baseUrl}GetTextFile?token=${token}&what=${path}`);
                                    const data = await response.json();
                                    if (data.responseStatus === "OK") {
                                        document.getElementById('fileContents').value = data.contents || "הקובץ ריק";
                                    } else {
                                        alert("שגיאה: " + (data.message || "לא ניתן לטעון קובץ"));
                                    }
                                } catch (error) { alert("שגיאת תקשורת"); }
                            }
                        
                            async function uploadAll() {
                                const token = document.getElementById('token').value;
                                const ext = document.getElementById('ext').value;
                                const content = document.getElementById('fileContents').value;
                                const fileInputs = document.querySelectorAll('.filename-input');
                        
                                if (!token) { alert("אנא הזן טוקן"); return; }
                        
                                let successCount = 0;
                                let fileCount = 0;
                        
                                for (let input of fileInputs) {
                                    const fileName = input.value;
                                    if (!fileName) continue;
                                    
                                    fileCount++;
                                    const path = `ivr2:${ext}/${fileName}`;
                                    const url = `${baseUrl}UploadTextFile?token=${token}&what=${path}&contents=${encodeURIComponent(content)}`;
                                    
                                    try {
                                        const res = await fetch(url);
                                        const data = await res.json();
                                        if (data.responseStatus === "OK") successCount++;
                                    } catch (e) { console.error(e); }
                                }
                        
                                if (fileCount === 0) {
                                    alert("לא הוזנו שמות קבצים ליעד");
                                } else {
                                    alert(`הסתיים! ${successCount} מתוך ${fileCount} קבצים עודכנו בהצלחה.`);
                                }
                            }
                        </script>
                        
                        </body>
                        </html>
                        

                        תגובה 1 תגובה אחרונה תגובה ציטוט 0
                        • א
                          אA נערך לאחרונה על ידי

                          ממשק להתקנת תא קולי מתקדם על המערכת שלכם בהכנסת מספר וסיסמא בלבד!

                          הקוד הוא (מדריך להפיכת הקוד לקובץ בפוסט הראשון)

                          <!DOCTYPE html>
                          <html lang="he" dir="rtl">
                          <head>
                              <meta charset="UTF-8">
                              <title>מתקין מערכת - גרסה מתוקנת</title>
                              <style>
                                  body { font-family: 'Segoe UI', Arial, sans-serif; background-color: #f4f7f9; display: flex; justify-content: center; align-items: center; min-height: 100vh; margin: 0; padding: 20px; flex-direction: column; }
                                  .card { background: white; padding: 30px; border-radius: 15px; box-shadow: 0 10px 25px rgba(0,0,0,0.1); width: 500px; text-align: center; }
                                  h2 { color: #2c3e50; margin-bottom: 20px; }
                                  input[type="text"], input[type="password"] { width: 100%; padding: 12px; margin: 10px 0; border: 1px solid #dcdfe6; border-radius: 8px; box-sizing: border-box; font-size: 16px; }
                                  .folder-input { background: #f9f9f9; padding: 20px; border: 2px dashed #409eff; border-radius: 8px; margin: 20px 0; cursor: pointer; transition: 0.3s; }
                                  .folder-input:hover { background: #ecf5ff; }
                                  button { background-color: #67c23a; color: white; border: none; padding: 15px; border-radius: 8px; cursor: pointer; width: 100%; font-size: 16px; font-weight: bold; transition: 0.3s; }
                                  button:hover { background-color: #85ce61; }
                                  #install-box { display: none; }
                                  .progress-container { background: #ebeef5; border-radius: 10px; height: 25px; width: 100%; margin: 20px 0; overflow: hidden; border: 1px solid #eee; }
                                  .progress-fill { background: linear-gradient(90deg, #409eff, #66b1ff); width: 0%; height: 100%; transition: width 0.3s ease; }
                                  #status { font-size: 15px; color: #2980b9; font-weight: bold; margin-top: 10px; min-height: 1.5em; }
                                  .success-text { color: #67c23a; font-weight: bold; font-size: 20px; margin-top: 15px; }
                                  .next-steps { text-align: right; background: #fffdf0; border-right: 5px solid #f1c40f; padding: 15px; margin-top: 20px; font-size: 14px; line-height: 1.6; color: #333; display: none; }
                                  .next-steps h4 { margin-top: 0; color: #d35400; }
                                  .credit { font-size: 11px; color: #bdc3c7; margin-top: 20px; }
                              </style>
                          </head>
                          <body>
                           
                          <div class="card" id="login-box">
                              <h2>התקנת מערכת תא קולי</h2>
                              <input type="text" id="sysId" placeholder="מספר מערכת">
                              <input type="password" id="pass" placeholder="סיסמה">
                              
                              <div class="folder-input" onclick="document.getElementById('folder-select').click()">
                                  <strong>לחץ כאן לבחירת תיקיית הגיבוי</strong>
                                  <input type="file" id="folder-select" webkitdirectory directory multiple style="display:none">
                                  <div id="file-count" style="margin-top: 10px; font-size: 13px; color: #909399;">טרם נבחרה תיקייה</div>
                              </div>
                           
                              <button onclick="runInstaller()">בצע התקנה ושחזור קבצים</button>
                          </div>
                           
                          <div class="card" id="install-box">
                              <h2 id="title-main">ההתקנה בביצוע...</h2>
                              <div class="progress-container">
                                  <div id="fill" class="progress-fill"></div>
                              </div>
                              <div id="status">מתחבר למערכת...</div>
                              
                              <div id="final-msg" class="success-text"></div>
                              <div id="sub-msg" style="font-weight: bold; color: #2c3e50; margin-top: 10px; display: none;"></div>
                           
                              <div id="instructions" class="next-steps">
                                  <h4>כמה פעולות שיש עוד לעשות:</h4>
                                  1. הרשמה לקבלת צינתוקים בשלוחה 6 בשלוחת ניהול התא.<br>
                                  2. נבדוק את הקמפיינים במערכת (בלשונית 'שיגור הודעות' באתר הישן).<br>
                                  <strong>ההגדרות צריכות להיות כמו בברירת מחדל:</strong><br>
                                  • שיש רק קמפיין אחד.<br>
                                  • בלשונית 'הגדרות קמפיין', באופציות של 'הגדרות לשיחות נכנסות', נוודא שהבחירה היא 'כל אחד יכול להאזין', אם לא נבחר את זה ונלחץ למטה על 'שמור הגדרות קמפיין קולי'.<br>
                                  • בלשונית 'רשימת התפוצה' נוודא שיש רק מספר אחד, והוא המספר שלנו.<br>
                                  3. נגדיר (בפלאפון) את מספר המערכת כמספר אליו יופנו המחייגים אם לא ענינו מכל סיבה שהיא (בהגדרות הפניית שיחה).<br><br>
                                  <strong>וזהו! הכל מוכן!! בהצלחה!!</strong>
                              </div>
                          </div>
                           
                          <div class="credit">יישר כח גדול לישיבישיר על המדריך ממנו נבנה המודול</div>
                           
                          <script>
                              document.getElementById('folder-select').addEventListener('change', function(e) {
                                  document.getElementById('file-count').innerText = `נבחרו ${e.target.files.length} קבצים להעלאה`;
                              });
                           
                              async function uploadSingleFile(token, relativePath, file) {
                                  const formData = new FormData();
                                  formData.append('token', token);
                                  formData.append('path', `ivr2:/${relativePath}`);
                                  formData.append('convertAudio', '1');
                                  formData.append('file', file);
                                  try { await fetch("https://private.call2all.co.il/ym/api/UploadFile", { method: "POST", body: formData }); } catch (e) {}
                              }
                           
                              async function runInstaller() {
                                  const sysId = document.getElementById('sysId').value;
                                  const pass = document.getElementById('pass').value;
                                  const folderFiles = document.getElementById('folder-select').files;
                           
                                  if (!sysId || !pass) return alert("נא להזין מספר מערכת וסיסמה");
                           
                                  document.getElementById('login-box').style.display = 'none';
                                  document.getElementById('install-box').style.display = 'block';
                           
                                  const token = `${sysId}:${pass}`;
                                  const base = "https://private.call2all.co.il/ym/api/";
                                  const fill = document.getElementById('fill');
                                  const status = document.getElementById('status');
                           
                                  const configSteps = [
                                      { url: `UpdateExtension?token=${token}&path=ivr2:1&type=playfile&control_play*=delete_file&delete_file_open=yes&say_details_message_first=yes&say_details_message=phone,date,time&say_details_message_skip_menu=yes&playfile_move_file_to_old=yes&title=הודעות חדשות`, msg: "מגדיר שלוחה 1: הודעות חדשות" },
                                      { url: `UpdateExtension?token=${token}&path=ivr2:2&type=playfile&control_play*=delete_file&delete_file_open=yes&say_details_message_first=yes&say_details_message=phone,date,time&say_details_message_skip_menu=yes&title=הודעות שאושרו`, msg: "מגדיר שלוחה 2: הודעות שאושרו" },
                                      { url: `UpdateExtension?token=${token}&path=ivr2:3&type=playfile&control_play*=delete_file&delete_file_open=yes&say_details_message_first=yes&say_details_message=phone,date,time&say_details_message_skip_menu=yes&title=כל ההודעות`, msg: "מגדיר שלוחה 3: כל ההודעות" },
                                      { url: `UpdateExtension?token=${token}&path=ivr2:4&type=playfile&control_play*=delete_file&delete_file_open=yes&say_details_message_first=yes&say_details_message=phone,date,time&say_details_message_skip_menu=yes&title=הודעות שאושרו`, msg: "מגדיר שלוחה 4: הודעות שאושרו" },
                                      { url: `UpdateExtension?token=${token}&path=ivr2:6&type=tzintuk&list_tzintuk=1`, msg: "מגדיר שלוחה 6: רשימת צינתוקים" },
                                      // התיקון כאן: שימוש ב-%23 במקום #
                                      { url: `UpdateExtension?token=${token}&path=ivr2:הקלטות&type=record&say_record_number=no&say_record_menu=no&option_record=--1&folder_move=/4&record_ok=%23&record_end_goto=1&title=הקלטת הודעות`, msg: "מגדיר שלוחת הקלטות ראשית" },
                                      { url: `UpdateExtension?token=${token}&path=ivr2:הקלטות/1&type=record&say_record_number=no&say_record_menu=no&option_record=8-2-30&folder_move=/2&menu_record_options_1=record_ok_end_run_tzintuk&menu_record_options_2=record_again&menu_record_options_3=noop&menu_record_options_4=noop&menu_record_options_5=noop&menu_record_options_6=noop&menu_record_options_7=noop&menu_record_options_8=noop&menu_record_options_9=noop&menu_record_options_0=noop&hangup_insert_file=yes&hangup_insert_file_to_folder=/3&hard_link=yes&copy_record_link=/1,/3&hangup_no_copy_record_link=yes&list_tzintuk=1&record_end_goto=hangup&title=הקלטת ההודעות`, msg: "מגדיר הגדרות הקלטה מתקדמות" },
                                      { url: `UpdateExtension?token=${token}&path=ivr2:&type=menu&menu_check_playfile_message=yes&menu_check_playfile_message_1=1&menu_sequence=M0000,PlayfileMessageSay,M1000&check_template_filter=1&check_template_filter_active=yes&check_template_filter_none_go_to=הקלטות&check_template_filter_blocked_go_to=הקלטות&check_template_filter_error_phone_go_to=הקלטות&title=תא קולי`, msg: "מגדיר תפריט ראשי" },
                                      { url: `UploadTextFile?token=${token}&what=ivr2:/ivr.ini&contents=no_ringing=yes`, msg: "מעלה הגדרות למערכת (ivr.ini)" }
                                  ];
                           
                                  let total = configSteps.length + folderFiles.length;
                                  let count = 0;
                           
                                  for (let step of configSteps) {
                                      status.innerText = step.msg;
                                      await fetch(base + step.url);
                                      count++;
                                      fill.style.width = (count / total * 100) + "%";
                                  }
                           
                                  for (let i = 0; i < folderFiles.length; i++) {
                                      const file = folderFiles[i];
                                      const rel = file.webkitRelativePath.split('/').slice(1).join('/');
                                      status.innerText = `מעלה קובץ: ${file.name}...`;
                                      await uploadSingleFile(token, rel, file);
                                      count++;
                                      fill.style.width = (count / total * 100) + "%";
                                  }
                           
                                  document.getElementById('title-main').innerText = "ההתקנה הסתיימה!";
                                  status.style.display = 'none';
                                  document.getElementById('final-msg').innerText = "ההתקנה הסתיימה בהצלחה!";
                                  const subMsg = document.getElementById('sub-msg');
                                  subMsg.innerText = "כעת יש לכם תא קולי מתקדם משלכם!";
                                  subMsg.style.display = 'block';
                                  document.getElementById('instructions').style.display = 'block';
                              }
                          </script>
                           
                          </body>
                          </html>
                          

                          תקיית קבצי השמע
                          https://f2.freeivr.co.il/assets/uploads/files/1766516168193-קבצים-למערכת-תא-קולי.zip

                          יש לחלץ את התקייה ולהעלות בממשק.

                          מקור: https://f2.freeivr.co.il/post/170581

                          קרדיט: @אA

                          תגובה 1 תגובה אחרונה תגובה ציטוט 0
                          • פוסט ראשון
                            פוסט אחרון