瀏覽代碼

change url

andy 7 月之前
父節點
當前提交
357a074567
共有 3 個文件被更改,包括 325 次插入33 次删除
  1. 36 1
      css/custom.css
  2. 65 20
      index.html
  3. 224 12
      js/demo/text-to-chart.js

+ 36 - 1
css/custom.css

@@ -54,6 +54,7 @@ body{
 background-repeat: no-repeat;
 background-size: cover;
 background-position: center;
+padding: 30px;
 }
 
 #data_chartJs_box{
@@ -100,7 +101,7 @@ background-position: center;
 }
 
 .chartSettingBox{
-    height: 78vh;
+    height: 90vh;
 }
 
 
@@ -124,12 +125,26 @@ background-position: center;
     object-fit: cover;
 }
 
+
+
 #chartdiv {
     width: 90%;
     height: 400px;
     overflow: visible; /* 显示超出容器的内容 */
   }
 
+  .autocomplete-suggestions2 {
+    display: none;
+    border: 1px solid #ccc;
+    max-height: 150px;
+    overflow-y: auto;
+    position: absolute;
+    top:55px;
+    z-index: 1000;
+    background: #fff;
+    width: 90%;
+}
+
   .autocomplete-suggestions {
     display: none;
     border: 1px solid #ccc;
@@ -266,6 +281,26 @@ background-position: center;
 
 }
 
+.unit_box{
+    position: absolute;
+    bottom: 180px;
+    left: 30px;
+    color:#584B3D;
+    text-shadow:
+    -1px -1px 0 #fff,  
+    1px -1px 0 #fff,
+    -1px 1px 0 #fff,
+    1px 1px 0 #fff;
+    font-size: 24px;
+    font-family: "Noto Sans TC", sans-serif;
+    font-optical-sizing: auto;
+    font-weight: 600;
+}
+.unit_value{
+    writing-mode: vertical-rl; /* 或者 vertical-lr 根據需求選擇 */
+    text-orientation: upright; /* 使文字保持正直 */
+    white-space: nowrap; /* 防止換行 */
+}
 .img_box{
     position: absolute;
     bottom: 91px;

+ 65 - 20
index.html

@@ -197,27 +197,47 @@
                                             <!-- <div id="legend" class="mt-3"></div> -->
                                             <div id="data_chart_box" class="chart_box2" style="position: relative;">
                                                 <h2 class="chart_title"></h2>
-                                                <div style="padding:0px 30px 30px;">
-                                                    <div id="data_chartJs_box"
-                                                        style="position: relative;  height: auto; text-align: center;">
-                                                        <canvas id="textToChart"></canvas>
-                                                        <!-- <div id="chart-label"></div> -->
-                                                        <!-- <div class="chart-line" id="chart-line"></div> -->
+                                                <!-- <div style="padding:0px 30px 30px;"> -->
+                                                <div id="data_chartJs_box"
+                                                    style="position: relative;  height: auto; text-align: center;">
+                                                    <canvas id="textToChart"></canvas>
+                                                    <!-- <div id="chart-label"></div> -->
+                                                    <!-- <div class="chart-line" id="chart-line"></div> -->
 
-                                                        <div id="chartdiv"></div>
+                                                    <div id="chartdiv"></div>
 
 
-                                                    </div>
+                                                </div>
 
+                                                <div id="unit_box" class="unit_box">
+                                                    <div class="unit_value"><span class="unit"></span></div>
                                                 </div>
+                                                <!-- </div> -->
                                                 <div id="img_box" class="img_box">
                                                     <img id="img_box_url" src="" alt="">
                                                 </div>
                                             </div>
                                         </div>
+                                        <div class="input-group pr-5 pl-5 compare mt-3 d-none">
+                                            <input type="text" style="position: relative ; z-index: 100;"
+                                                id="keyword_data_compare" class="form-control bg-white small"
+                                                placeholder="搜尋股票、ETF 或其他項目進行比較..." aria-label="Search"
+                                                aria-describedby="basic-addon2">
+                                            <div id="suggestions_compare" class="autocomplete-suggestions2"></div>
+                                            <div class="input-group-append">
+                                                <button class="btn btn-primary" type="button">
+                                                    <!-- <i class="fas fa-search fa-sm"></i> -->
+                                                    比較
+                                                </button>
+
+                                            </div>
+                                        </div>
                                     </div>
+
+
                                 </div>
                             </div>
+
                         </div>
 
                     </div>
@@ -363,9 +383,19 @@
         </form>
         <form class="ml-md-3 mr-md-3 my-2 chartSetting ">
             <p class="font-weight-bold">標題:</p>
-            <input type="text" id="title_data" class="form-control bg-light small mb-3" placeholder="請輸入標題..."
-                aria-label="Search" aria-describedby="basic-addon2">
-            <p class="font-weight-bold">標題位置:</p>
+            <div class="d-flex">
+                <div style="width: 75%;">
+                    <input type="text" id="title_data" class="form-control bg-light small mb-3" placeholder="請輸入標題..."
+                        aria-label="Search" aria-describedby="basic-addon2">
+                </div>
+                <div style="width: 20%; margin-left: 5px;">
+                    <input type="number" value="32" step="1" class="form-control" id="TitlefontSize" />
+
+                </div>
+
+            </div>
+
+            <!-- <p class="font-weight-bold">標題位置:</p>  -->
             <div class="form-check form-check-inline">
                 <input class="form-check-input" value="0" type="radio" name="inlineRadioOptions" id="inlineRadio1"
                     value="option1" checked>
@@ -381,27 +411,30 @@
                     value="option2">
                 <label class="form-check-label" for="inlineRadio3">置右</label>
             </div>
+            <p class="font-weight-bold">單位:</p>
+            <input type="text" id="unit_data" class="form-control bg-light small mb-3" aria-label="Search2"
+                aria-describedby="basic-addon2">
         </form>
-        <form class="ml-md-3 mr-md-3 my-2">
+
+        <!-- <form class="ml-md-3 mr-md-3 my-2">
 
             <div>
                 <p class="font-weight-bold">標題字體大小:</p>
                 <label class="d-none" for="TitlefontSize">字體大小:</label>
                 <input type="number" value="32" step="1" class="form-control" id="TitlefontSize" />
             </div>
-        </form>
+        </form> -->
 
         <form class="ml-md-3 mr-md-3 my-2 chartSetting d-none">
             <div>
                 <p class="font-weight-bold">縱軸:</p>
-                <input type="text" id="unit_data" class="form-control bg-light small mb-3" placeholder="請輸入單位..."
-                    aria-label="Search" aria-describedby="basic-addon2">
+
             </div>
             <div class="ml-4 d-flex">
                 <div>
-                    <p class="font-weight-bold">圖表字體大小:</p>
+                    <!-- <p class="font-weight-bold">圖表字體大小:</p>
                     <label class="d-none" for="YfontSize">字體大小:</label>
-                    <input type="number" value="18" step="1" class="form-control" id="YfontSize" />
+                    <input type="number" value="18" step="1" class="form-control" id="YfontSize" /> -->
                 </div>
 
             </div>
@@ -415,11 +448,12 @@
         </form>
         <div id="lineChartSetting">
             <form class="ml-md-3 mr-md-3 my-2 chartSetting">
-                <p class="font-weight-bold">橫軸:</p>
+                <p class="font-weight-bold">橫字體大小:</p>
                 <label class="d-none" for="XfontSize">字體大小:</label>
                 <input type="number" value="18" step="1" class="form-control" id="XfontSize" />
             </form>
-            <form class="ml-md-3 mr-md-3 my-2 chartSetting">
+
+            <form class="ml-md-3 mr-md-3 my-3 chartSetting">
                 <div id="borderSetting" class="borderWidth d-flex">
                     <div>
                         <p class="font-weight-bold">線條粗細:</p>
@@ -436,7 +470,18 @@
                 </div>
                 <div>
                 </div>
-                <input type="checkbox" id="togglePoints"> 顯示數據點
+
+
+                <div id="lineYfontSize">
+                    <p class="font-weight-bold">數據字體大小:</p>
+                    <label class="d-none" for="YfontSize">字體大小:</label>
+                    <input type="number" value="18" step="1" class="form-control" id="YfontSize" />
+                </div>
+
+                <div class="mt-3">
+                    顯示數據點:<input class="ml-3" type="checkbox" id="togglePoints">
+
+                </div>
             </form>
         </div>
 

+ 224 - 12
js/demo/text-to-chart.js

@@ -3,27 +3,40 @@
 console.log('text-to-chart');
 
 var accessToken = localStorage.getItem("access_token");
+console.log(accessToken);
+
+if (accessToken === null) {
+    alert('請先登入')
+    window.location.href = "./login.html";
+}
 
 var usernameEmail = localStorage.getItem("username");
 
+var unit_table_value
+
 
 
 let username = usernameEmail.split('@')[0];
 
 console.log(username);
 
-console.log(accessToken);
 
 
 Chart.register(ChartDataLabels);
 
 var userNameSpan = document.getElementById("userName");
 
+var lineYfontSize = document.getElementById("lineYfontSize");
+
+
 
 userNameSpan.textContent = username;
 
 var inputField = document.getElementById("keyword_data");
 
+var inputField_compare = document.getElementById("keyword_data_compare");
+
+
 var sendButton = document.getElementById("send_data");
 
 var canvasPng = document.getElementById("textToChart");
@@ -58,6 +71,9 @@ var vocab = [];
 
 var chartDiv = document.getElementById('chartdiv');
 
+$('#chartdiv').hide();
+
+
 document.addEventListener('DOMContentLoaded', function () {
     axios.get("https://cmm.ai:8080/vocab")
         .then(response => {
@@ -183,6 +199,108 @@ document.addEventListener('DOMContentLoaded', function () {
     });
 });
 
+document.addEventListener('DOMContentLoaded', function () {
+    // const input = document.getElementById('stockInput');
+    const suggestions_compare = document.getElementById('suggestions_compare');
+
+    inputField_compare.addEventListener('input', function () {
+        const query = this.value.trim();
+        suggestions_compare.innerHTML = ''; // 清空之前的建議
+
+        console.log('query', query);
+        if (query) {
+            // const filteredVocab = vocab.filter(item => item.toLowerCase().includes(query));
+            const queryTerms = query.split(/\s+/); // 分割輸入的內容
+            const lastQueryTerm = queryTerms[queryTerms.length - 1];
+            const filteredVocab = vocab.filter(item => {
+                // 對每個分割後的單詞進行匹配,只要其中有一個匹配成功就返回 true
+                return item.toLowerCase().includes(lastQueryTerm.toLowerCase());
+
+            });
+
+
+            if (filteredVocab.length > 0) {
+                suggestions_compare.style.border = '1px solid #ccc';
+                suggestions_compare.style.display = 'block'; // 顯示建議容器
+            } else {
+                suggestions_compare.style.border = 'none';
+                suggestions_compare.style.display = 'none'; // 隱藏建議容器
+            }
+
+            console.log(queryTerms[queryTerms.length - 1])
+
+            filteredVocab.forEach(item => {
+                const div = document.createElement('div');
+                div.classList.add('autocomplete-suggestion');
+                div.textContent = item;
+                // div.addEventListener('click', function () {
+                //     inputField.value = item;
+                //     suggestions.innerHTML = ''; // 清空建議
+                //     suggestions.style.border = 'none';
+                //     suggestions.style.display = 'none'; // 隱藏建議容器
+
+                // });
+                console.log('queryTerms', queryTerms);
+
+                // console.log('filteredVocab', filteredVocab);
+
+
+                div.addEventListener('click', function () {
+                    queryTerms.forEach((term, index) => {
+                        const regex = new RegExp(term, 'gi');
+                        const match = regex.exec(inputField_compare.value);
+                        // console.log(queryTerms[queryTerms.length - 1]);
+                        // console.log(filteredVocab, queryTerms[queryTerms.length - 1])
+
+                        if (index === queryTerms.length - 1) {
+
+                            if (match) {
+                                var start = match.index;
+                                var end = start + match[0].length;
+
+                                console.log(start, end)
+
+                                const textBefore = inputField_compare.value.substring(0, start);
+                                const textAfter = inputField_compare.value.substring(end, inputField_compare.value.length);
+
+                                console.log('start', start, 'end', end, 'textBefore', textBefore, 'textAfter', textAfter);
+
+                                // 捕獲被選中的部分並替換它
+                                const selectedText = inputField_compare.value.substring(start, end);
+
+                                console.log('selectedText', selectedText);
+
+
+                                const newText = textBefore + item + textAfter.replace(selectedText, '');
+
+                                console.log('newText', newText);
+
+                                inputField_compare.value = newText;
+                                // inputField.value = textBefore + item.replace(selectedText, '') + textAfter;
+
+                                suggestions_compare.innerHTML = ''; // 清空建議
+                                suggestions_compare.style.border = 'none';
+                            }
+                        }
+
+                    });
+
+                    // const start = inputField.selectionStart;
+                    // const end = inputField.selectionEnd;
+
+
+                });
+
+                suggestions_compare.appendChild(div);
+
+            });
+        } else {
+            suggestions_compare.style.border = 'none';
+            suggestions_compare.style.display = 'none'; // 隱藏建議容器
+        }
+    });
+});
+
 // 監聽輸入框的鍵盤事件
 // document.getElementById("keyword_data").addEventListener("keyup", function (event) {
 //     // 判斷是否按下 Enter 鍵 (key code: 13)
@@ -299,7 +417,14 @@ var data = [];
 
 var dataArray;
 
+
+
 function generateChart(dataArray) {
+    if (dataArray.length > 10) {
+        lineYfontSize.style.display = 'none'
+    } else {
+        lineYfontSize.style.display = 'block'
+    }
     // 创建一个空数组来存储 labels 和 data
     console.log(dataArray)
     // 遍历数据数组
@@ -874,7 +999,8 @@ var chartJsBox = document.getElementById('data_chartJs_box');
 function createTable(dataArray, unit, Label_dependent_variable, Label_independent_variable,) {
     $('#chartdiv').hide();
     $('#textToChart').hide();
-
+    chartTitle.style.padding = "0px 0px 0px 30px";
+    bgImgelement.style.paddingTop = "10px";
     var table = document.createElement('table');
     table.classList.add('table', 'table_template', 'dynamic-table'); // 添加 Bootstrap 的 table 样式,如果你在使用 Bootstrap
 
@@ -909,10 +1035,14 @@ function createTable(dataArray, unit, Label_dependent_variable, Label_independen
                 cell.classList.add('year-class');
             } else { // Otherwise, add 'average-class'
                 if (key === 'Average_Close') {
-                    cell.textContent = item[key].toFixed(2) + unit;
+                    // cell.textContent = item[key].toFixed(2) + unit;
+                    cell.innerHTML = item[key].toFixed(2) + '<span class="unit_table">' + unit + '</span>';
+
                 } else {
                     // cell.textContent = item[key];
-                    cell.textContent = item[key].toFixed(2) + unit;
+                    // cell.textContent = item[key].toFixed(2) + unit;
+                    cell.innerHTML = item[key].toFixed(2) + '<span class="unit_table">' + unit + '</span>';
+
                 }
                 cell.classList.add('average-class');
             }
@@ -938,8 +1068,37 @@ function createTable(dataArray, unit, Label_dependent_variable, Label_independen
     // chartWhitelement.style.background = "rgba(255,255,255,0.5)"
     // 将表格添加到指定的 div 元素中
     chartJsBox.appendChild(table);
+
+    unit_table_value = document.querySelectorAll('.unit_table');
+
+
+    downloadButton.style.display = "inline-block";
+
 }
 
+function getDatalabelsConfig(dataLength) {
+
+    if (dataLength < 10) {
+        return {
+            formatter: function (value, context) {
+                return value + ' unit'; // Add unit if data length is less than 10
+            },
+            textStrokeColor: '#fff',
+            textStrokeWidth: 5,
+            color: '#584B3D',
+            font: {
+                size: YfontSizeValue,
+            },
+            anchor: 'end',
+            align: 'end',
+        };
+    } else {
+        return null; // No datalabels if data length is 10 or more
+    }
+}
+
+
+
 // 版型一折線圖
 // // 创建 Chart.js 图表
 function createChart(chartType, data, labels) {
@@ -947,6 +1106,22 @@ function createChart(chartType, data, labels) {
     canvasPng.style.maxWidth = '';
     canvasPng.style.maxHeight = '';
 
+
+
+    const datalabelsConfig = data.length <= 10 ? {
+        formatter: function (value, context) {
+            return value;
+        },
+        textStrokeColor: '#fff',
+        textStrokeWidth: 5,
+        color: '#584B3D',
+        font: {
+            size: YfontSizeValue,
+        },
+        anchor: 'end',
+        align: 'right'
+    } : null;
+
     ctx = document.getElementById("textToChart");
 
     myChart = new Chart(ctx, {
@@ -974,16 +1149,18 @@ function createChart(chartType, data, labels) {
             maintainAspectRatio: false,
 
             plugins: {
+
                 chart3d: {
                     enabled: true, // 啟用 3D 插件
                     alpha: 25, // 圖表繞 x 軸的旋轉角度
                     beta: 25, // 圖表繞 y 軸的旋轉角度
                     depth: 15 // 圖表的深度
                 },
+                datalabels: datalabelsConfig,
                 // datalabels: {
                 //     formatter: function (value, context) {
                 //         // 添加单位
-                //         return value + ' ' + unit;
+                //         return value;
                 //     },
                 //     textStrokeColor: '#fff',
                 //     textStrokeWidth: 5,
@@ -994,7 +1171,8 @@ function createChart(chartType, data, labels) {
                 //     anchor: 'end',
                 //     align: 'end',
                 // },
-                datalabels: null,
+
+                // datalabels: null, 
                 // datalabels: data.length <= 10 ? {
                 //     formatter: function (value, context) {
                 //         // 添加单位
@@ -1234,17 +1412,34 @@ togglePoints.addEventListener('change', function () {
 });
 
 
-// 單位標題
+// 單位
 // =========================
 var unitInput = document.getElementById('unit_data');
 
+var unit_value = document.querySelector('.unit');
+
+
+// console.log('單位', unitInput)
+
 unitInput.addEventListener('input', function () {
-    unit = unitInput.value;
+    // unitInput.value = unit_value.textContent;
+
+    if (chartType === 'table') {
+        // unit_table_value.textContent = this.value;
+        unit_table_value.forEach(span => {
+            span.textContent = this.value;
+        });
+    } else {
+        unit_value.textContent = '單位:' + this.value
+
+    }
+
 
-    // 重新渲染图表
-    myChart.update();
 });
 
+
+
+
 // ==========================
 
 // y軸字體大小-折線圖
@@ -1449,6 +1644,8 @@ radioButtons.forEach(button => {
     });
 });
 
+// 圖表標題
+
 var keywordInput = document.getElementById('title_data');
 
 
@@ -1493,12 +1690,14 @@ function get_data(input_text_value) {
         labels = [];
         console.log('已存在')
         chartTitle.textContent = "";
+        unit_value.textContent = "";
         bgImgelement.style.backgroundImage = "";
         chartWhitelement.style.background = "";
         document.getElementById('img_box_url').src = "";
     }
 
     if (existingTable) {
+        unit_value.textContent = "";
         chartJsBox.removeChild(existingTable);
         chartTitle.textContent = "";
         bgImgelement.style.backgroundImage = "";
@@ -1507,6 +1706,7 @@ function get_data(input_text_value) {
 
     }
     if (myChart) {
+        unit_value.textContent = "";
         data = [];
         labels = [];
         chartTitle.textContent = "";
@@ -1549,12 +1749,19 @@ function get_data(input_text_value) {
 
 
                 unit_data.value = response.data.chart_info.Unit_of_dependent_variable;
+                if (response.data.chart_info.Unit_of_dependent_variable == "") {
+                    unit_value.textContent = ""
+                } else {
+                    unit_value.textContent = '單位:' + response.data.chart_info.Unit_of_dependent_variable;
+
+                }
 
 
                 dataArray = response.data.data;
 
 
                 if (chartType === "table") {
+                    unit_value.textContent = "";
                     createTable(dataArray, unit, Label_dependent_variable, Label_independent_variable);
                     // document.getElementById('img_box_url').src = "";
 
@@ -1563,6 +1770,7 @@ function get_data(input_text_value) {
                     $('#textToChart').hide();
                     extractAndGenerateChart(dataArray);
                 } else if (chartType === "doughnut") {
+                    unit_value.textContent = "";
                     $('#textToChart').hide();
 
                     generatePieChart(dataArray)
@@ -2169,7 +2377,7 @@ async function handleAudioToText(file) {
             break;
     }
 
-    let url = `https://bf18-61-230-0-215.ngrok-free.app/gcp/speech-to-text?language_code=${audioLang}`;
+    let url = `https://9cbe-61-230-36-113.ngrok-free.app/gcp/speech-to-text?language_code=${audioLang}`;
 
     const formData = new FormData();
     formData.append("file", file);
@@ -2178,9 +2386,13 @@ async function handleAudioToText(file) {
         const response = await axios.post(url, formData);
         console.log("response", response);
         input_text_value = response.data;
-        console.log(input_text_value[0]);
         recording_block.classList.remove('show');
         recording_block.classList.add('hidden');
+        if (input_text_value.length === 0) {
+            alert('請再說一次')
+            return
+        }
+        console.log(input_text_value[0]);
         get_data(input_text_value);
 
     } catch (error) {