1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019 |
- 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
- var obj = {
- _text: ''
- };
- // let username = usernameEmail.split('@')[0];
- Chart.register(ChartDataLabels);
- var userNameSpan = document.getElementById("userName");
- var lineYfontSize = document.getElementById("lineYfontSize");
- userNameSpan.textContent = usernameEmail;
- var inputField = document.getElementById("keyword_data");
- var inputField_compare = document.getElementById("keyword_data_compare");
- var compare_box = document.getElementById("compare");
- var sendButton = document.getElementById("send_data");
- var send_data_compare = document.getElementById("data_compare");
- var canvasPng = document.getElementById("textToChart");
- var img_box = document.getElementById("img_box");
- var sidebar = document.getElementById('style_setting');
- var input_text_value;
- var chartType = 'line';
- var unit = '';
- var myChart = null;
- var chartColor = '#912B2B';
- var chartColorBar = '#'
- var displayXaxes = true;
- var ctx;
- var chartlabels;
- var chartdata;
- var XfontSizeValue = 16;
- var YfontSizeValue = 18;
- var TitlefontSizeValue = 32;
- var pieFontSize = 14;
- var PieMaxWidth = 100;
- var pointRadiusValue = 0;
- var pointHoverRadiusValue = 0;
- var chart_bgimg_url = "url(./img/bg06.webp)";
- var vocab = [];
- var vocab_compare = [];
- var chartDiv = document.getElementById('chartdiv');
- var dataFirstValue;
- var dataLastValue;
- let cancelToken;
- let source;
- $('#chartdiv').hide();
- var clickExample = document.getElementById('example_box')
- document.addEventListener('DOMContentLoaded', function () {
- axios.get("https://cmm.ai:8080/vocab")
- .then(response => {
- // apiHideLoading();
- console.log(response);
- vocab = response.data;
- })
- .catch(error => {
- console.error('發生錯誤:', error);
- });
- });
- // 比較提示詞
- document.addEventListener('DOMContentLoaded', function () {
- axios.get("https://cmm.ai:8080/vocab_comparision")
- .then(response => {
- // apiHideLoading();
- console.log(response);
- vocab_compare = response.data;
- })
- .catch(error => {
- console.error('發生錯誤:', error);
- });
- });
- inputField.addEventListener('click', function () {
- // 確保輸入框處於焦點狀態
- inputField.focus();
- // 在控制台中顯示焦點狀態
- console.log('Input field focused');
- });
- document.addEventListener('DOMContentLoaded', function () {
- // const input = document.getElementById('stockInput');
- const suggestions = document.getElementById('suggestions');
- inputField.addEventListener('input', function () {
- const query = this.value.trim();
- suggestions.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.style.border = '1px solid #ccc';
- suggestions.style.display = 'block'; // 顯示建議容器
- } else {
- suggestions.style.border = 'none';
- suggestions.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.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.value.substring(0, start);
- const textAfter = inputField.value.substring(end, inputField.value.length);
- console.log('start', start, 'end', end, 'textBefore', textBefore, 'textAfter', textAfter);
- // 捕獲被選中的部分並替換它
- const selectedText = inputField.value.substring(start, end);
- console.log('selectedText', selectedText);
- const newText = textBefore + item + textAfter.replace(selectedText, '');
- console.log('newText', newText);
- inputField.value = newText;
- // inputField.value = textBefore + item.replace(selectedText, '') + textAfter;
- suggestions.innerHTML = ''; // 清空建議
- suggestions.style.border = 'none';
- }
- }
- });
- // const start = inputField.selectionStart;
- // const end = inputField.selectionEnd;
- });
- suggestions.appendChild(div);
- });
- } else {
- suggestions.style.border = 'none';
- suggestions.style.display = 'none'; // 隱藏建議容器
- }
- });
- });
- 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_compare.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)
- // if (event.keyCode === 13) {
- // // 觸發送出按鈕的點擊事件
- // document.getElementById("send_data").click();
- // }
- // });
- // 定義按鈕點擊事件處理函數
- function sendButtonClickHandler() {
- // inputField.value = "";
- console.log(inputField.value);
- var input_text_value = inputField.value;
- // input_text_value = '台積電近兩週收盤價'
- compare_box.style.display = "none";
- $('#chartdiv').hide();
- sidebar.classList.remove('show');
- sidebar.classList.add('hidden');
- // 在這裡添加你希望在按下按鈕時執行的其他代碼
- get_data(input_text_value);
- }
- sendButton.addEventListener("click", function () {
- sendButtonClickHandler();
- inputField.value = ''
- unit_value_box.style.display = "none"
- chartTypeBtn.style.display = "none";
- });
- let labels2 = [];
- let data2 = [];
- // 漲幅or單價
- const checkbox1 = document.getElementById('checkbox1');
- const checkbox2 = document.getElementById('checkbox2');
- var compare_type_input = document.querySelector('.checkbox-group')
- var compare_type = "";
- checkbox1.addEventListener('change', () => {
- if (checkbox1.checked) {
- checkbox2.checked = false;
- compare_type = '漲幅'
- console.log(compare_type);
- }
- });
- checkbox2.addEventListener('change', () => {
- if (checkbox2.checked) {
- checkbox1.checked = false;
- compare_type = '單價'
- console.log(compare_type);
- }
- });
- send_data_compare.addEventListener("click", function () {
- console.log('比較', inputField_compare.value);
- const stockName = inputField_compare.value;
- axios
- .get(`https://cmm.ai:8080/get_data_from_date?start_date=${dataFirstValue}&end_date=${dataLastValue}&stock_name=${inputField_compare.value}`)
- .then((response) => {
- console.log(response);
- var compare_data = response.data.data;
- labels2 = []; // Clear previous labels
- data2 = []; // Clear previous data
- if (compare_type === "") {
- alert('請輸入比較類型');
- return
- }
- // console.log('比較送出後 ', chartType)
- if (response.data.data === "無法產生圖表") {
- alert('無法產生圖表')
- return
- }
- if (chartType === 'line') {
- const colors = [
- '#82a33f', // rgba already
- '#2f487b', // rgba already
- '#df8c49', // hex #df8c49
- '#72598f', // hex #72598f
- '#489fb6', // hex #489fb6
- '#99b0d5' // hex #99b0d5
- ];
- let colorIndex = 0;
- for (var i = 0; i < compare_data.length; i++) {
- var item = compare_data[i];
- // 遍历当前项的属性
- for (var key in item) {
- // 如果属性名不在 labels 数组中,并且属性值不是对象,则将属性名添加到 labels 数组中
- if (typeof item[key] === 'string') {
- labels2.push(item[key]);
- }
- // 如果属性值是数值类型,则将其添加到 data 数组中
- if (typeof item[key] === 'number') {
- data2.push(item[key]);
- }
- }
- }
- function getRandomColor() {
- const randomIndex = Math.floor(Math.random() * colors.length);
- const selectedColor = colors[randomIndex];
- colors.splice(randomIndex, 1); // 从数组中移除已选颜色
- return selectedColor;
- }
- const normalize = (prices) => {
- const initialPrice = prices[0];
- // return prices.map(price => (price - initialPrice) / initialPrice * 100);
- return prices.map(price => {
- // Calculate the normalized price
- const normalized = (price - initialPrice) / initialPrice * 100;
- // Round to 2 decimal places and convert back to a number
- return parseFloat(normalized.toFixed(2));
- });
- };
- var stock2Normalized;
- var stock1Normalized;
- if (compare_type === '漲幅') {
- console.log('漲幅')
- stock2Normalized = normalize(data2);
- stock1Normalized = normalize(data);
- unitInput.value = '%';
- unit_value.textContent = '%'
- } else {
- console.log('單價')
- unitInput.value = unitInput.value;
- unit_value.textContent = unitInput.value;
- stock2Normalized = data2;
- stock1Normalized = data;
- }
- const color = getRandomColor();
- if (response.data.data.length < 15) {
- pointRadiusValue = 5;
- pointHoverRadiusValue = 0;
- togglePoints.checked = true;
- }
- const newDataset = {
- label: stockName,
- backgroundColor: color,
- pointRadius: pointRadiusValue,
- pointHoverRadius: 0,
- pointBorderColor: '#fff',
- pointBorderWidth: 3,
- pointHoverRadiusValue: 8,
- borderColor: color,
- data: stock2Normalized,
- fill: false
- };
- colorIndex = (colorIndex + 1) % colors.length;
- myChart.data.datasets.push(newDataset);
- myChart.data.datasets[0].data = stock1Normalized;
- console.log('多筆資料', myChart.data.datasets);
- // console.log('比較', myChart.options.plugins.legend);
- myChart.options.plugins.legend.display = true;
- // myChart.defaults.global.legend = {
- // display: true,
- // position: 'top', // 默认图例位置为顶部
- // labels: {
- // fontColor: 'rgb(255, 99, 132)', // 默认图例标签颜色
- // fontSize: 14 // 默认图例标签字体大小
- // }
- // };
- myChart.update();
- inputField_compare.value = '';
- compare_type_input.style.display = 'none'
- } else if (chartType === 'bar') {
- }
- })
- .catch((error) =>
- console.log(error)
- );
- });
- // sendButton.addEventListener("click", function () {
- // console.log(inputField.value);
- // input_text_value = inputField.value;
- // // if (myChart) {
- // // console.log('已存在')
- // // data = [];
- // // labels = [];
- // // myChart.removePlugin(Chart.pluginService.getPlugin('afterDraw'));
- // // myChart.destroy();
- // // }
- // get_data(input_text_value);
- // });
- var lastKeyPressTime = 0;
- var enterCount = 0;
- var ENTER_THRESHOLD = 500; // 設定連續按下 Enter 的時間閾值(毫秒)
- inputField.addEventListener("keyup", function (event) {
- // 判斷是否按下 Enter 鍵 (key code: 13)
- if (event.key === "Enter") {
- var currentTime = new Date().getTime();
- // 計算與上一次按鍵按下時間的差值
- var timeDiff = currentTime - lastKeyPressTime;
- lastKeyPressTime = currentTime;
- // 如果兩次 Enter 鍵按下的時間差小於閾值,則增加計數器
- if (timeDiff <= ENTER_THRESHOLD) {
- enterCount++;
- // 如果計數器為2,則觸發 API 請求並重置計數器
- if (enterCount === 2) {
- sendButtonClickHandler();
- enterCount = 0;
- }
- } else {
- // 如果時間差大於閾值,則重置計數器
- enterCount = 0;
- }
- } else {
- // 如果按下的不是 Enter 鍵,則重置計數器
- enterCount = 0;
- }
- });
- function number_format(number, decimals, dec_point, thousands_sep) {
- // * example: number_format(1234.56, 2, ',', ' ');
- // * return: '1 234,56'
- number = (number + '').replace(',', '').replace(' ', '');
- var n = !isFinite(+number) ? 0 : +number,
- prec = !isFinite(+decimals) ? 0 : Math.abs(decimals),
- sep = (typeof thousands_sep === 'undefined') ? ',' : thousands_sep,
- dec = (typeof dec_point === 'undefined') ? '.' : dec_point,
- s = '',
- toFixedFix = function (n, prec) {
- var k = Math.pow(10, prec);
- return '' + Math.round(n * k) / k;
- };
- // Fix for IE parseFloat(0.55).toFixed(0) = 0;
- s = (prec ? toFixedFix(n, prec) : '' + Math.round(n)).split('.');
- if (s[0].length > 3) {
- s[0] = s[0].replace(/\B(?=(?:\d{3})+(?!\d))/g, sep);
- }
- if ((s[1] || '').length < prec) {
- s[1] = s[1] || '';
- s[1] += new Array(prec - s[1].length + 1).join('0');
- }
- return s.join(dec);
- }
- var labels = [];
- var data = [];
- function apiLoading() {
- document.getElementById('chartDataLoading').style.display = 'block';
- }
- function apiHideLoading() {
- document.getElementById('chartDataLoading').style.display = 'none';
- }
- const DISPLAY = true;
- const BORDER = true;
- const CHART_AREA = true;
- const TICKS = true;
- var labels = [];
- var data = [];
- var dataArray;
- // get_data('2330近兩週收盤價');
- function generateChart(dataArray) {
- if (dataArray.length > 15) {
- lineYfontSize.style.display = 'none'
- } else {
- lineYfontSize.style.display = 'block'
- }
- // 创建一个空数组来存储 labels 和 data
- console.log(dataArray)
- // 遍历数据数组
- for (var i = 0; i < dataArray.length; i++) {
- var item = dataArray[i];
- // 遍历当前项的属性
- for (var key in item) {
- // 如果属性名不在 labels 数组中,并且属性值不是对象,则将属性名添加到 labels 数组中
- if (typeof item[key] === 'string') {
- labels.push(item[key]);
- } else {
- if (key === 'x') {
- labels.push(String(item[key]));
- }
- }
- if (key === 'y') {
- data.push(item[key]);
- }
- // 如果属性值是数值类型,则将其添加到 data 数组中
- // if (typeof item[key] === 'number') {
- // data.push(item[key]);
- // }
- }
- }
- console.log(data);
- dataFirstValue = labels[0];
- dataLastValue = labels[labels.length - 1]
- console.log('dataFirstValue', dataFirstValue);
- console.log('dataLastValue', dataLastValue);
- if (myChart) {
- console.log('已存在')
- myChart.destroy();
- }
- if (chartType === "doughnut") {
- // createChartDoughnut(chartType, data, labels);
- // createChartDoughnut2(data, labels)
- } else {
- createChart(chartType, data, labels);
- }
- // console.log(data);
- console.log(labels);
- }
- var amChartInstance;
- function extractAndGenerateChart(dataArray) {
- for (var i = 0; i < dataArray.length; i++) {
- var item = dataArray[i];
- // 遍历当前项的属性
- for (var key in item) {
- // 如果属性名不在 labels 数组中,并且属性值不是对象,则将属性名添加到 labels 数组中
- if (typeof item[key] === 'string') {
- labels.push(item[key]);
- }
- // 如果属性值是数值类型,则将其添加到 data 数组中
- if (typeof item[key] === 'number') {
- data.push(item[key]);
- }
- }
- }
- // console.log('key', key);
- generateBarChart(key, dataArray);
- }
- // 圓餅圖
- function generatePieChart(dataArray, pieFontSize, PieMaxWidth) {
- compare_box.style.display = "none";
- $('#chartdiv').show();
- bgImgelement.style.backgroundImage = chart_bgimg_url;
- // chartDiv.style.width = "100%"
- chartWhitelement.style.background = "rgba(255,255,255,0.5)"
- // Themes begin
- am4core.useTheme(am4themes_animated);
- // Themes end
- // Create chart instance
- var chart = am4core.create("chartdiv", am4charts.PieChart);
- chart.data = dataArray;
- chart.innerRadius = am4core.percent(50);
- // Add and configure Series
- var pieSeries = chart.series.push(new am4charts.PieSeries());
- pieSeries.dataFields.value = "y";
- pieSeries.dataFields.category = "x";
- pieSeries.slices.template.stroke = am4core.color("#fff");
- pieSeries.slices.template.strokeWidth = 2;
- pieSeries.slices.template.strokeOpacity = 1;
- // Configure labels
- pieSeries.labels.template.wrap = true;
- console.log('PieMaxWidth', PieMaxWidth);
- pieSeries.labels.template.maxWidth = PieMaxWidth;
- pieSeries.labels.template.truncate = false;
- pieSeries.labels.template.fontSize = 14;
- if (typeof PieMaxWidth === 'string') {
- console.log('The variable is a string.');
- } else {
- console.log('The variable is a number.');
- }
- // Configure label text to wrap and show percentages
- // pieSeries.labels.template.adapter.add("textOutput", function (text, target) {
- // if (target.dataItem && target.dataItem.values.value.percent) {
- // return "[font-size: 14px]" + target.dataItem.category + ": " + target.dataItem.values.value.percent.toFixed(1) + "%";
- // }
- // return text;
- // });
- pieSeries.labels.template.adapter.add("textOutput", function (text, target) {
- if (target.dataItem && target.dataItem.values.value.percent) {
- return "[font-size: " + pieFontSize + "px]" + target.dataItem.category + ": " + target.dataItem.values.value.percent.toFixed(1) + "%";
- }
- return text;
- });
- pieSeries.colors.list = [
- am4core.color('rgb(171, 51, 49)'),
- am4core.color('rgb(34, 83, 149)'),
- am4core.color('rgb(79, 148, 65)'),
- am4core.color('rgb(217, 195, 105)'),
- am4core.color('rgb(142, 124, 180)'),
- am4core.color('rgb(211, 183, 144)'),
- am4core.color('rgb(83, 84, 84)'),
- am4core.color('rgb(229, 147, 152)')
- ];
- // Ensure labels have background
- // pieSeries.labels.template.background.fillOpacity = 1;
- console.log(pieSeries.labels.template)
- // Set label background color to match corresponding slice color
- pieSeries.labels.template.adapter.add("background.fill", function (fill, target) {
- return target.dataItem.slice.fill;
- });
- // This creates initial animation
- pieSeries.hiddenState.properties.opacity = 1;
- pieSeries.hiddenState.properties.endAngle = -90;
- pieSeries.hiddenState.properties.startAngle = -90;
- // console.log('調位置')
- downloadButton.style.display = "inline-block";
- chartTypeBtn.style.display = "inline-block";
- }
- // var colorEven='#288D97';
- // var colorOdd='#427D7E'
- function adjustColorBrightness(color, amount) {
- let usePound = false;
- if (color[0] == "#") {
- color = color.slice(1);
- usePound = true;
- }
- let num = parseInt(color, 16);
- let r = (num >> 16) + amount;
- let g = ((num >> 8) & 0x00FF) + amount;
- let b = (num & 0x0000FF) + amount;
- if (r > 255) r = 255;
- else if (r < 0) r = 0;
- if (g > 255) g = 255;
- else if (g < 0) g = 0;
- if (b > 255) b = 255;
- else if (b < 0) b = 0;
- return (usePound ? "#" : "") + (r << 16 | g << 8 | b).toString(16).padStart(6, '0');
- }
- // 柱狀圖
- function generateBarChart(key, dataArray) {
- console.log('generateBarChart', dataArray)
- chartTypeBtn.style.display = "inline-block";
- compare_box.style.display = "none";
- $('#chartdiv').show();
- // var colorEven = document.getElementById('colorEven').value;
- // var colorOdd = document.getElementById('colorOdd').value;
- var baseColor = document.getElementById('borderColorInputBar').value;
- var categoryAxisFzValue = document.getElementById('XfontSizeBar').value;
- var valueAxisFzValue = document.getElementById('YfontSizeBar').value;
- var colorEven = am4core.color(baseColor);
- var colorOdd = adjustColorBrightness(baseColor, -20);
- chartDiv.style.fontFamily = "Arial, sans-serif";
- chartDiv.style.fontWeight = "900";
- bgImgelement.style.backgroundImage = chart_bgimg_url;
- chartWhitelement.style.background = "rgba(255,255,255,0.5)"
- console.log('labelDependent', labelDependent);
- // Themes begin
- am4core.useTheme(am4themes_animated);
- // Themes end
- // Create chart instance
- var chart = am4core.create("chartdiv", am4charts.XYChart3D);
- chart.data = dataArray;
- chart.angle = 30; // 圖表角度
- chart.depth = 25; // 圖表深度
- let categoryAxis = chart.xAxes.push(new am4charts.CategoryAxis());
- categoryAxis.dataFields.category = "x";
- categoryAxis.renderer.labels.template.rotation = 0;
- categoryAxis.renderer.labels.template.hideOversized = false;
- categoryAxis.renderer.minGridDistance = 20; // 間距
- // categoryAxis.renderer.labels.template.horizontalCenter = "left";
- // categoryAxis.renderer.labels.template.verticalCenter = "middle";
- // categoryAxis.tooltip.label.rotation = 90;
- // categoryAxis.tooltip.label.horizontalCenter = "right";
- // categoryAxis.tooltip.label.verticalCenter = "middle";
- // label 換行
- let label = categoryAxis.renderer.labels.template;
- label.wrap = true;
- if (dataArray.length > 8) {
- console.log('資料長度5')
- label.maxWidth = 50;
- }
- else if (dataArray.length < 7) {
- label.maxWidth = 80;
- } else {
- label.maxWidth = 100;
- console.log('資料長度<5')
- }
- // x軸字體大小
- categoryAxis.renderer.labels.template.fontSize = categoryAxisFzValue;
- categoryAxis.renderer.cellEndLocation = 0.5; // 減少值可以增加間距
- let valueAxis = chart.yAxes.push(new am4charts.ValueAxis());
- valueAxis.title.text = labelDependent; // Y軸
- valueAxis.title.fontWeight = "bold";
- // y軸字體大小
- valueAxis.renderer.labels.template.fontSize = valueAxisFzValue;
- // Create series
- var series = chart.series.push(new am4charts.ColumnSeries3D());
- series.dataFields.valueY = 'y';
- series.dataFields.categoryX = "x";
- series.name = "y";
- series.tooltipText = "{categoryX}: [bold]{valueY}[/]";
- series.columns.template.fillOpacity = .8;
- let columnTemplate = series.columns.template;
- columnTemplate.strokeWidth = 2;
- columnTemplate.strokeOpacity = 1;
- columnTemplate.stroke = am4core.color("#FFFFFF");
- // columnTemplate.adapter.add("fill", function (fill, target) {
- // return chart.colors.getIndex(target.dataItem.index);
- // })
- // 設置基數和偶數顏色
- columnTemplate.adapter.add("fill", function (fill, target) {
- return target.dataItem.index % 2 === 0 ? am4core.color(colorEven) : am4core.color(colorOdd);
- });
- columnTemplate.adapter.add("stroke", function (stroke, target) {
- return chart.colors.getIndex(target.dataItem.index);
- })
- // // 加上白色線條
- // series.columns.template.events.on("validated", function (event) {
- // let column = event.target;
- // let whiteLine = column.createChild(am4core.Line);
- // whiteLine.stroke = am4core.color("#ffffff");
- // whiteLine.strokeWidth = 1.3; // 線條寬度
- // whiteLine.strokeOpacity = 0.5;// 透明度
- // whiteLine.x1 = column.pixelWidth / 1;
- // whiteLine.y1 = 0;
- // whiteLine.x2 = column.pixelWidth / 1;
- // whiteLine.y2 = column.pixelHeight;
- // });
- chart.cursor = new am4charts.XYCursor();
- chart.cursor.lineX.strokeOpacity = 0;
- chart.cursor.lineY.strokeOpacity = 0;
- categoryAxis.renderer.grid.template.strokeOpacity = 0; // 隱藏 X 軸
- // valueAxis.renderer.grid.template.strokeOpacity = 0; // 隱藏 Y 軸
- // valueAxis.renderer.line.strokeOpacity = 0;
- // LineSeries 底部線條
- var lineSeries = chart.series.push(new am4charts.LineSeries());
- lineSeries.dataFields.valueY = "bottom";
- lineSeries.dataFields.categoryX = "0";
- lineSeries.stroke = am4core.color("#FFFFFF")
- lineSeries.strokeWidth = 2;
- lineSeries.strokeOpacity = 1
- var bottomData = [];
- for (var i = 0; i < dataArray.length; i++) {
- bottomData.push({ "x": dataArray[i].x, "bottom": 0 });
- }
- lineSeries.data = bottomData;
- downloadButton.style.display = "inline-block";
- chartTypeBtn.style.display = "inline-block";
- chartTypeBtn.style.opacity = "1";
- // 底部線條
- // let rectElements = document.querySelectorAll("rect");
- // // let widthValue = 0;
- // let fifthRectElement = rectElements[3];
- // // fifthRectElement.style.position = "relative";
- // setTimeout(() => {
- // let width = fifthRectElement.getAttribute("width");
- // // widthValue = parseFloat(width);
- // console.log('rectElements', rectElements);
- // console.log('fifthRectElement', fifthRectElement);
- // console.log('width', width);
- // let line = document.createElement("div");
- // line.style.position = "absolute";
- // line.style.bottom = "162px";
- // line.style.right = "40px";
- // line.style.width = `${parseFloat(width)}px`;
- // line.style.height = "2px";
- // line.style.backgroundColor = "#000000";
- // document.getElementById("chartdiv").appendChild(line);
- // }, 10)
- // end am4core.ready()
- }
- function handleClick(element) {
- const Clickvalue = element.dataset.value;
- console.log(Clickvalue); // 123
- get_data(Clickvalue);
- }
- // 圖表類型
- var chartTypeBtn = document.getElementById("chartType");
- chartTypeBtn.addEventListener('change', function () {
- const selectedValue = this.value;
- console.log('選擇的圖表類型:', selectedValue);
- obj.text = selectedValue;
- // 在此处添加处理选定图表类型的代码
- if (selectedValue === 'line') {
- // 处理折线图
- console.log('處理折線圖', dataArray);
- $('#chartdiv').hide();
- chartType = 'line';
- if (myChart) {
- data = [];
- labels = [];
- myChart.destroy();
- }
- sidebar.classList.add('hidden');
- generateChart(dataArray);
- } else if (selectedValue === 'bar') {
- chartType = 'bar';
- $('#textToChart').hide();
- // 处理柱状图
- console.log('處理柱狀圖', dataArray);
- sidebar.classList.add('hidden');
- extractAndGenerateChart(dataArray);
- } else if (selectedValue === 'doughnut') {
- chartType = 'doughnut';
- console.log('處理圓餅圖', dataArray);
- unit_value.textContent = "";
- $('#textToChart').hide();
- sidebar.classList.add('hidden');
- generatePieChart(dataArray, pieFontSize, PieMaxWidth)
- // 处理圆饼图
- }
- });
- var downloadButton = document.getElementById("downloadButton");
- // downloadButton.style.display = 'none';
- // 添加點擊事件監聽器
- downloadButton.addEventListener('click', function () {
- setTimeout(function () {
- // html2canvas(document.getElementById('data_chart_box')).then(function (canvas) {
- // // // 獲取圖片資料 URL
- // // var imageData = canvasPng.toDataURL("image/png");
- // // // 創建下載連結
- // // var link = document.createElement('a');
- // // link.download = 'chart.png'; // 下載的檔案名稱
- // // link.href = imageData; // 圖片資料 URL
- // // // 模擬點擊下載連結
- // // link.click();
- // // 創建一個<a>元素
- // const link = document.createElement('a');
- // // 將 Canvas 轉換為 Data URL
- // link.href = canvas.toDataURL('image/png');
- // // 設置下載文件名
- // link.download = 'chart.png';
- // // 模擬點擊下載
- // link.click();
- // });
- html2canvas(document.getElementById('data_chart_box'), {
- backgroundColor: null, // 確保背景透明
- scale: 2,
- useCORS: true,
- scrollX: 0,
- scrollY: 0
- }).then(function (canvas) {
- // 創建一個 <a> 元素
- const link = document.createElement('a');
- // 將 Canvas 轉換為 Data URL
- link.href = canvas.toDataURL('image/png');
- // 設置下載文件名
- link.download = 'chart.png';
- // 模擬點擊下載
- link.click();
- });
- }, 1000); // 等待 1 秒钟
- });
- var pieChartColors = [
- 'rgb(171, 51, 49)',
- 'rgb(34, 83, 149)',
- 'rgb(79, 148, 65)',
- 'rgb(217, 195, 105)',
- 'rgb(142, 124, 180)',
- 'rgb(211, 183, 144)',
- 'rgb(83, 84, 84)',
- 'rgb(229, 147, 152)'
- ];
- function createChartDoughnut2(data, labels) {
- const chartData = {
- type: 'outlabeledPie',
- data: {
- labels: labels,
- datasets: [
- {
- data: data,
- borderWidth: borderWidthValue,
- fill: false,
- backgroundColor: pieChartColors,
- },
- ],
- },
- options: {
- plugins: {
- legend: false,
- outlabels: {
- text: '%l %p',
- color: 'white',
- stretch: 35,
- font: {
- resizable: true,
- family: 'Arial',
- size: 48,
- weight: 'bold',
- style: 'italic',
- },
- },
- },
- },
- };
- const devicePixelRatio = 4;
- var chartUrl = `https://quickchart.io/chart?c=${encodeURIComponent(JSON.stringify(chartData))}&devicePixelRatio=${devicePixelRatio}&f=png&fontsize=20`;
- // 获取目标 div 元素
- const targetDiv = document.getElementById('data_chartJs_box');
- // 创建一个 img 元素来显示图表
- const chartImg = document.createElement('img');
- chartImg.src = chartUrl;
- chartImg.classList.add('outlabeled_img');
- // 清空目标 div 元素
- targetDiv.innerHTML = '';
- // 将图表 img 元素插入到目标 div 中
- targetDiv.appendChild(chartImg);
- console.log(chart_bgimg_url);
- bgImgelement.style.backgroundImage = chart_bgimg_url;
- chartWhitelement.style.background = "rgba(255,255,255,0.5)"
- }
- // 版型二源餅圖
- // // 创建 Chart.js 图表
- function createChartDoughnut(chartType, data, labels) {
- $('#textToChart').show();
- canvasPng.style.maxWidth = '450px';
- canvasPng.style.maxHeight = '450px';
- var windowWidth = window.innerWidth || document.documentElement.clientWidth;
- var canvasWidth = Math.min(500, windowWidth); // 限制最大宽度为 500px
- canvasPng.style.width = canvasWidth + 'px'; // 设置 canvas 宽度
- canvasPng.style.marginLeft = 'auto'; // 左外边距自动计算
- canvasPng.style.marginRight = 'auto'; // 右外边距自动计算
- var ctx = document.getElementById("textToChart").getContext('2d');
- myChart = new Chart(ctx, {
- type: chartType,
- data: {
- labels: labels,
- datasets: [{
- strokeColor: "rgba(220,220,220,1)",
- StrokeWidth: 5,
- data: data,
- borderWidth: borderWidthValue,
- pointRadius: 0,
- pointBorderColor: '#fff',
- pointBorderWidth: 3,
- pointHoverRadius: 0,
- fill: false,
- backgroundColor: pieChartColors,
- // barPercentage: 0.5,
- // categoryPercentage: 0.5
- }]
- },
- options: {
- // responsive: true, // 啟用響應式
- maintainAspectRatio: true,
- responsive: true,
- aspectRatio: 1,
- plugins: {
- legend: {
- display: false,
- },
- datalabels: {
- color: '#fff', // 数据标签的颜色
- anchor: 'end', // 数据标签的位置
- align: 'start', // 数据标签的对齐方式
- font: {
- size: 14, // 数据标签的字体大小
- },
- }
- },
- scales: {
- x: {
- display: false, // 显示 x 轴
- grid: {
- display: false,
- lineWidth: 5,
- color: '#584B3D'
- },
- ticks: {
- textStrokeColor: '#fff',
- textStrokeWidth: 5,
- font: {
- display: false,
- family: 'Arial', // 设置字体
- size: XfontSizeValue, // 设置字体大小
- weight: 'bold', // 设置字体粗细
- fontColor: 'rgba(255,255,255,0.8)', // X-axis font color
- shadowColor: 'rgba(0, 0, 0, 0.5)', // Shadow color
- shadowBlur: 10, // Shadow blur level
- shadowOffsetX: 5, // Horizontal shadow offset
- shadowOffsetY: 5
- },
- },
- },
- y: {
- display: false,
- beginAtZero: false,
- grid: {
- display: false,
- lineWidth: 5,
- color: '#584B3D'
- },
- ticks: {
- textStrokeColor: '#fff',
- textStrokeWidth: 5,
- font: {
- family: 'Arial', // 設置字體
- size: XfontSizeValue, // 設置字體大小
- weight: 'bold', // 設置字體粗細
- color: 'rgba(255,255,255,0.8)', // Y-axis 字體顏色
- shadowColor: 'rgba(0, 0, 0, 0.5)', // 陰影顏色
- shadowBlur: 10, // 陰影模糊級別
- shadowOffsetX: 5, // 水平陰影偏移
- shadowOffsetY: 5 // 垂直陰影偏移
- },
- }
- }
- },
- layout: {
- padding: {
- left: 50, // 调整图表左边距
- right: 50, // 调整图表右边距
- top: 10,
- bottom: 10,
- }
- },
- },
- });
- console.log(chart_bgimg_url);
- bgImgelement.style.backgroundImage = chart_bgimg_url;
- chartWhitelement.style.background = "rgba(255,255,255,0.5)"
- }
- var chartJsBox = document.getElementById('data_chartJs_box');
- function createTable(dataArray, unit, Label_dependent_variable, Label_independent_variable,) {
- $('#chartdiv').hide();
- $('#textToChart').hide();
- chartTitle.style.padding = "15px 0px 30px 30px";
- bgImgelement.style.paddingTop = "10px";
- var table = document.createElement('table');
- table.classList.add('table', 'table_template', 'dynamic-table'); // 添加 Bootstrap 的 table 样式,如果你在使用 Bootstrap
- // 创建表头
- var thead = table.createTHead();
- var headerRow = thead.insertRow();
- // Object.keys(dataArray[0]).forEach(function (key) {
- // var header = headerRow.insertCell();
- // header.textContent = key;
- // });
- var yearHeader = headerRow.insertCell();
- yearHeader.textContent = Label_independent_variable;
- var avgPriceHeader = headerRow.insertCell();
- avgPriceHeader.textContent = Label_dependent_variable;
- // 创建表格主体
- var tbody = table.createTBody();
- dataArray.forEach(function (item) {
- console.log(item)
- var row = tbody.insertRow();
- // var cell1 = row.insertCell();
- // cell1.textContent = item.year;
- // cell1.classList.add('year-class'); // 为年份单元格添加类
- // var cell2 = row.insertCell();
- Object.keys(item).forEach(function (key, index) {
- var cell = row.insertCell();
- if (index === 0) { // If it's the first cell, add 'year-class'
- cell.textContent = item[key];
- cell.classList.add('year-class');
- } else { // Otherwise, add 'average-class'
- if (key === 'Average_Close') {
- // 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.innerHTML = item[key].toFixed(2) + '<span class="unit_table">' + unit + '</span>';
- }
- cell.classList.add('average-class');
- }
- });
- // console.log(item.avg_price.toFixed(2))
- // cell.textContent = item[key].toFixed(2) + unit;
- // cell2.classList.add('average-class'); // 为年份单元格添加类
- });
- // 获取包含表格的 div 元素
- bgImgelement.style.backgroundImage = chart_bgimg_url;
- img_box.style.bottom = '60px';
- img_box.style.right = '5px';
- document.getElementById('img_box_url').style.width = "180px";
- // 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";
- chartTypeBtn.style.display = "inline-block";
- chartTypeBtn.style.opacity = "0";
- }
- 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
- }
- }
- function getDatalabelsConfig(isEnabled) {
- if (!isEnabled) {
- return null;
- }
- return data.length <= 15 ? {
- formatter: function (value, context) {
- return value;
- },
- textStrokeColor: '#fff',
- textStrokeWidth: 5,
- color: '#584B3D',
- font: {
- size: YfontSizeValue,
- },
- anchor: 'end',
- align: 'top'
- } : null;
- }
- // 版型一折線圖
- // // 创建 Chart.js 图表
- function createChart(chartType, data, labels) {
- $('#textToChart').show();
- canvasPng.style.maxWidth = '';
- canvasPng.style.maxHeight = '';
- console.log('繪製圖表', data, labels);
- if (data.length < 15) {
- pointRadiusValue = 5;
- pointHoverRadiusValue = 0;
- togglePoints.checked = true;
- toggleValue.checked = true;
- } else {
- pointRadiusValue = 0;
- togglePoints.checked = false;
- toggleValue.checked = false;
- }
- const datalabelsConfig = data.length <= 15 ? {
- formatter: function (value, context) {
- // if (context.dataIndex === 0) {
- // return '';
- // }
- // if (typeof value === 'number' && value.toString().includes('.')) {
- // value = value.toFixed(4);
- // }
- // return value;
- return value;
- },
- textStrokeColor: '#fff',
- textStrokeWidth: 5,
- color: '#584B3D',
- font: {
- size: YfontSizeValue,
- },
- anchor: 'end',
- align: 'end',//固定
- offset: 5,
- } : null;
- ctx = document.getElementById("textToChart");
- myChart = new Chart(ctx, {
- type: chartType,
- data: {
- labels: labels,
- datasets: [{
- label: stocknumber,
- strokeColor: "rgba(220,220,220,1)",
- StrokeWidth: 5,
- data: data,
- borderWidth: borderWidthValue,
- pointRadius: pointRadiusValue,
- pointBorderColor: '#fff',
- pointBorderWidth: 3,
- // pointHoverRadius: 10,
- fill: false,
- backgroundColor: chartColor,
- borderColor: chartColor,
- hitRadius: 10,
- // barPercentage: 0.5,
- // categoryPercentage: 0.5
- }]
- },
- options: {
- responsive: true, // 啟用響應式
- maintainAspectRatio: false,
- plugins: {
- datalabels: datalabelsConfig,
- backgroundColor: 'transparent',
- // datalabels: {
- // formatter: function (value, context) {
- // // 添加单位
- // return value;
- // },
- // textStrokeColor: '#fff',
- // textStrokeWidth: 5,
- // color: '#584B3D',
- // font: {
- // size: YfontSizeValue,
- // },
- // anchor: 'end',
- // align: 'end',
- // },
- // datalabels: null,
- // datalabels: data.length <= 10 ? {
- // formatter: function (value, context) {
- // // 添加单位
- // return value + ' ' + unit;
- // },
- // textStrokeColor: '#fff',
- // textStrokeWidth: 5,
- // color: '#584B3D',
- // font: {
- // size: YfontSizeValue,
- // },
- // anchor: 'end',
- // align: 'end',
- // } : null,
- // customLabels: null,
- legend: {
- display: false,
- fullSize: true,
- position: 'bottom',
- onClick: function (e, legendItem, legend) {
- e.native.stopImmediatePropagation();
- // 獲取被點擊的數據集索引
- selectedDatasetIndex = legendItem.datasetIndex;
- const dataset_color = legend.chart.data.datasets[selectedDatasetIndex].borderColor;
- console.log(dataset_color)
- colorInput.value = dataset_color;
- // // 手動觸發 Chart.js 的默認圖例點擊事件
- // const defaultClickHandler = Chart.defaults.plugins.legend.onClick;
- // defaultClickHandler.call(this, e, legendItem, legend);
- }
- },
- },
- scales: {
- x: {
- display: displayXaxes, // 显示 x 轴
- grid: {
- display: false,
- lineWidth: 5,
- color: '#584B3D'
- },
- ticks: {
- textStrokeColor: '#fff',
- textStrokeWidth: 5,
- font: {
- display: false,
- family: 'Arial', // 设置字体
- size: XfontSizeValue, // 设置字体大小
- weight: 'bold', // 设置字体粗细
- fontColor: 'rgba(255,255,255,0.8)', // X-axis font color
- shadowColor: 'rgba(0, 0, 0, 0.5)', // Shadow color
- shadowBlur: 10, // Shadow blur level
- shadowOffsetX: 5, // Horizontal shadow offset
- shadowOffsetY: 5
- },
- },
- },
- y: {
- display: true,
- beginAtZero: false,
- grid: {
- grid: {
- display: true, // 显示 y 轴网格线
- lineWidth: 1, // 网格线宽度
- color: '#C0C5CC' // 网格线颜色
- },
- },
- ticks: {
- padding: 10,
- textStrokeColor: '#fff',
- textStrokeWidth: 5,
- font: {
- family: 'Arial', // 設置字體
- size: XfontSizeValue, // 設置字體大小
- weight: 'bold', // 設置字體粗細
- color: 'rgba(255,255,255,0.8)', // Y-axis 字體顏色
- shadowColor: 'rgba(0, 0, 0, 0.5)', // 陰影顏色
- shadowBlur: 10, // 陰影模糊級別
- shadowOffsetX: 5, // 水平陰影偏移
- shadowOffsetY: 5 // 垂直陰影偏移
- },
- }
- }
- },
- layout: {
- padding: {
- left: 50, // 调整图表左边距
- right: 50, // 调整图表右边距
- top: 40,
- bottom: 10,
- }
- },
- onClick: function (event, elements) {
- if (elements.length > 0) {
- const element = elements[0];
- selectedDatasetIndex = element.datasetIndex;
- const currentColor = myChart.data.datasets[selectedDatasetIndex].borderColor;
- const colorValue = currentColor;
- colorInput.value = colorValue;
- // 获取当前线条颜色并更新 colorPicker
- // colorInput.value = rgbToHex(currentColor);
- // console.log('當前顏色', colorValue);
- colorInput.disabled = false; // 启用 colorPicker
- }
- },
- },
- });
- console.log('第一次', myChart.options.legend)
- console.log(chart_bgimg_url);
- bgImgelement.style.backgroundImage = chart_bgimg_url;
- chartWhitelement.style.background = "rgba(255,255,255,0.5)";
- downloadButton.style.display = "inline-block";
- chartTypeBtn.style.display = "inline-block";
- chartTypeBtn.style.opacity = "1";
- compare_box.style.display = "flex";
- }
- // createChart(chartType);
- // createChart(chartType)
- const ChartOptions = document.querySelectorAll('input[name="ChartOptions"]');
- ChartOptions.forEach(button => {
- button.addEventListener('click', function () {
- // console.log(this.value);
- chartType = this.value;
- console.log(chartType);
- if (myChart !== null) {
- myChart.destroy();
- data = [];
- labels = [];
- }
- if (chartType === 'line') {
- $('#chartdiv').hide();
- generateChart(dataArray);
- } else {
- $('#textToChart').hide();
- extractAndGenerateChart(dataArray);
- }
- // createChart(chartType, data, labels);
- });
- });
- // 表格字體
- var fontSizeInput = document.getElementById('table_fontSize');
- // 添加事件监听器
- fontSizeInput.addEventListener('input', function () {
- // 获取输入框的值
- var fontSize = fontSizeInput.value;
- // 获取动态创建的表格元素
- var dynamicTable = document.querySelector('.dynamic-table');
- // 如果表格存在,则调整其字体大小
- if (dynamicTable) {
- dynamicTable.style.fontSize = fontSize + 'px';
- }
- });
- // 圓餅圖字體
- var pieFontSizeInput = document.getElementById('pie_fontSize');
- // 添加事件监听器
- pieFontSizeInput.addEventListener('input', function () {
- // 获取输入框的值
- pieFontSize = pieFontSizeInput.value;
- console.log('圓餅圖字體', pieFontSize);
- if (pieFontSize) {
- generatePieChart(dataArray, pieFontSize, PieMaxWidth);
- } else {
- alert("Please enter a valid font size.");
- }
- // 如果表格存在,则调整其字体大小
- // if (dynamicTable) {
- // dynamicTable.style.fontSize = fontSize + 'px';
- // }
- });
- document.getElementById('PieMaxWidthRange').addEventListener('input', function () {
- PieMaxWidth = Number(document.getElementById('PieMaxWidthRange').value);
- console.log('圓餅圖', PieMaxWidth)
- generatePieChart(dataArray, pieFontSize, PieMaxWidth);
- });
- // 是否顯示point
- var togglePoints = document.getElementById('togglePoints');
- togglePoints.addEventListener('change', function () {
- console.log('checked', "change")
- // 遍历所有数据集,应用相应的pointRadius和pointHoverRadius
- myChart.data.datasets.forEach(function (dataset) {
- if (togglePoints.checked) {
- dataset.pointRadius = 5;
- dataset.pointHoverRadius = 8;
- } else {
- dataset.pointRadius = 0;
- dataset.pointHoverRadius = 0;
- }
- });
- myChart.update();
- });
- // 是否顯示數值
- var toggleValue = document.getElementById('toggleValue');
- let datalabelsConfig = getDatalabelsConfig(toggleValue.checked);
- toggleValue.addEventListener('change', function () {
- console.log('切換數值')
- // 根据复选框状态更新 datalabelsConfig
- datalabelsConfig = getDatalabelsConfig(this.checked);
- // 更新图表
- myChart.options.plugins.datalabels = datalabelsConfig;
- myChart.update();
- });
- // 是否顯示x軸
- const toggleXAxis = document.getElementById('toggleXAxis');
- toggleXAxis.addEventListener('change', function () {
- // 根据复选框的状态来显示或隐藏 X 轴
- myChart.options.scales.x.ticks.display = this.checked;
- // 更新图表
- myChart.update();
- });
- // 是否顯示單位
- var toggleUnit = document.getElementById('toggleUnit');
- toggleUnit.addEventListener('change', function () {
- if (this.checked) {
- unit_value_box.style.display = 'block';
- } else {
- unit_value_box.style.display = 'none';
- }
- });
- // 單位
- // =========================
- var unitInput = document.getElementById('unit_data');
- var unit_value = document.querySelector('.unit');
- var unit_value_box = document.querySelector('#unit_box');
- // console.log('單位', unitInput)
- unitInput.addEventListener('input', function () {
- // 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;
- }
- });
- // ==========================
- // y軸字體大小-折線圖
- // ==========================
- var YfontSize = document.getElementById('YfontSize');
- YfontSize.addEventListener('input', function () {
- YfontSizeValue = YfontSize.value;
- const newSize = parseInt(YfontSizeValue);
- // 更新 datalabelsConfig 的字体大小
- myChart.options.plugins.datalabels.font.size = newSize;
- // 更新图表
- myChart.update();
- // createChart(chartType, data, labels);
- });
- // ==========================
- // x軸字體大小-折線圖
- // ==========================
- var XfontSize = document.getElementById('XfontSize');
- XfontSize.addEventListener('input', function () {
- XfontSizeValue = XfontSize.value;
- // console.log(XfontSizeValue)
- // if (myChart) {
- // myChart.destroy();
- // }
- // 修改X轴标签字体大小
- myChart.options.scales.x.ticks.font.size = parseInt(XfontSizeValue);
- myChart.options.scales.y.ticks.font.size = parseInt(XfontSizeValue);
- myChart.update();
- // createChart(chartType, data, labels);
- });
- // ==========================
- // x軸字體大小-柱狀圖
- // ==========================
- var XfontSizeBar = document.getElementById('XfontSizeBar');
- XfontSizeBar.addEventListener('input', function () {
- extractAndGenerateChart(dataArray);
- });
- // ==========================
- // y軸字體大小-柱狀圖
- // ==========================
- var YfontSizeBar = document.getElementById('YfontSizeBar');
- YfontSizeBar.addEventListener('input', function () {
- extractAndGenerateChart(dataArray);
- });
- // ==========================
- // 線條顏色-柱狀圖
- // =========================
- const colorInputBar = document.getElementById('borderColorInputBar');
- // 添加事件监听器,当颜色选择发生变化时触发
- colorInputBar.addEventListener('input', function () {
- extractAndGenerateChart(dataArray);
- });
- // =========================
- // 線條粗細
- // =========================
- function updateLineWidth(borderWidthValue) {
- myChart.data.datasets.forEach(dataset => {
- dataset.borderWidth = parseFloat(borderWidthValue);
- });
- myChart.update();
- }
- var rangeInput = document.getElementById('borderWidthRange');
- // var rangeInputSpan = document.getElementById('borderWidthRangeValue');
- var borderWidthValue;
- // rangeInputSpan.textContent = rangeInput.value;
- // 添加事件监听器,当滑动条的值发生改变时更新显示的值
- rangeInput.addEventListener('input', function () {
- // 获取滑动条的当前值
- borderWidthValue = rangeInput.value;
- console.log(borderWidthValue);
- // rangeInputSpan.textContent = borderWidthValue;
- updateLineWidth(borderWidthValue);
- // myChart.data.datasets[0].borderWidth = borderWidthValue;
- });
- // =========================
- // 線條顏色-折線圖
- // =========================
- const colorInput = document.getElementById('borderColorInput');
- let selectedDatasetIndex = null;
- // 添加事件监听器,当颜色选择发生变化时触发
- colorInput.addEventListener('input', function () {
- // 获取当前选择的颜色值
- // chartColor = colorInput.value;
- // if (myChart) {
- // myChart.destroy();
- // }
- if (selectedDatasetIndex !== null) {
- const newColor = colorInput.value;
- myChart.data.datasets[selectedDatasetIndex].borderColor = newColor;
- myChart.data.datasets[selectedDatasetIndex].backgroundColor = newColor;
- myChart.update(); // 更新图表
- // createChart(chartType, data, labels);
- }
- // console.log(chartColor);
- // createChart(chartType, data, labels);
- });
- function rgbToHex(rgb) {
- const rgbArr = rgb.match(/\d+/g);
- return `#${((1 << 24) + (parseInt(rgbArr[0]) << 16) + (parseInt(rgbArr[1]) << 8) + parseInt(rgbArr[2])).toString(16).slice(1)}`;
- }
- function hexToRgba(hex, alpha = 1) {
- // 移除 HEX 颜色值的 # 符号
- hex = hex.replace(/^#/, '');
- // 处理 3 位 HEX 颜色值(如 #fff)
- if (hex.length === 3) {
- hex = hex.split('').map(function (hex) {
- return hex + hex;
- }).join('');
- }
- // 解析 HEX 颜色值
- const r = parseInt(hex.substring(0, 2), 16);
- const g = parseInt(hex.substring(2, 4), 16);
- const b = parseInt(hex.substring(4, 6), 16);
- // 返回 RGBA 颜色值
- return `rgba(${r}, ${g}, ${b}, ${alpha})`;
- }
- // =========================
- // 模板樣式
- // =========================
- // JavaScript
- document.addEventListener("DOMContentLoaded", function () {
- // 獲取所有帶有 templateImg class 的圖像元素
- var templateImgs = document.querySelectorAll('.templateImg');
- // 為每個圖像元素添加點擊事件監聽器
- templateImgs.forEach(function (img) {
- img.addEventListener('click', function () {
- // 在點擊時印出圖像元素的 value 屬性值
- console.log(this.getAttribute('value'));
- });
- });
- });
- // =========================
- var bgImgelement = document.getElementById('data_chart_box');
- var chartWhitelement = document.getElementById('data_chartJs_box');
- // 背景樣式
- // =========================
- // JavaScript
- document.addEventListener("DOMContentLoaded", function () {
- // 獲取所有帶有 templateImg class 的圖像元素
- var bgImgs = document.querySelectorAll('.bgImg');
- // 為每個圖像元素添加點擊事件監聽器
- bgImgs.forEach(function (img) {
- img.addEventListener('click', function () {
- // 在點擊時印出圖像元素的 value 屬性值
- console.log(this.getAttribute('value'));
- var bgImgUrl = this.getAttribute('value');
- chart_bgimg_url = 'url(' + bgImgUrl + ')';
- if (bgImgUrl === './img/bg07.webp') {
- chartTitle.style.color = "#ffff";
- chartTitle.style.padding = '0px'
- }
- else {
- chartTitle.style.color = "#1c2d6d";
- }
- if (bgImgUrl === "") {
- chartWhitelement.style.background = "";
- console.log('無背景');
- bgImgelement.style.backgroundImage = "";
- chartWhitelement.style.background = 'rgba(255, 255, 255, 0) !important;'
- } else {
- bgImgelement.style.backgroundImage = chart_bgimg_url;
- chartWhitelement.style.background = "rgba(255, 255, 255, 0.5)"
- }
- // bgImgelement.style.backgroundSize = 'cover'; // 調整背景圖片大小
- // bgImgelement.style.backgroundPosition = 'center'; // 調整背景圖片位置
- // bgImgelement.style.backgroundRepeat = 'no-repeat'; // 調整背景圖片重複
- });
- });
- });
- // =========================
- const radioButtons = document.querySelectorAll('input[name="inlineRadioOptions"]');
- var chartTitle = document.querySelector('.chart_title');
- radioButtons.forEach(button => {
- button.addEventListener('click', function () {
- if (this.value === '0') {
- chartTitle.style.textAlign = 'left';
- } else if (this.value === '1') {
- chartTitle.style.textAlign = 'center';
- } else if (this.value === '2') {
- chartTitle.style.textAlign = 'right';
- }
- });
- });
- // 圖表標題
- var keywordInput = document.getElementById('title_data');
- // 初始时将输入框的值设置为标题的文本内容
- keywordInput.value = chartTitle.textContent;
- // 监听输入框的输入事件,实现内容同步更新
- keywordInput.addEventListener('input', function () {
- chartTitle.textContent = this.value;
- });
- // 標題字體大小
- // ==========================
- var TitlefontSize = document.getElementById('TitlefontSize');
- TitlefontSize.addEventListener('input', function () {
- var TitlefontSizeValue = TitlefontSize.value;
- chartTitle.style.fontSize = TitlefontSizeValue + 'px';;
- });
- // 標題字體顏色
- var stocknumber;
- // ==========================
- let labelDependent = ""; // 圖表左側 Label
- function get_data(input_text_value) {
- clickExample.style.display = 'none'
- // 重新创建取消令牌和源
- cancelToken = axios.CancelToken;
- source = cancelToken.source();
- // inputField.value = "";
- apiLoading();
- var existingTable = chartJsBox.querySelector('table');
- downloadButton.style.display = "none";
- if (chartDiv.childElementCount != 0) {
- data = [];
- 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 = "";
- chartWhitelement.style.background = "";
- document.getElementById('img_box_url').src = "";
- }
- if (myChart) {
- unit_value_box.style.display = 'none';
- unit_value.textContent = "";
- data = [];
- labels = [];
- chartTitle.textContent = "";
- bgImgelement.style.backgroundImage = "";
- chartWhitelement.style.background = "";
- myChart.destroy();
- document.getElementById('img_box_url').src = "";
- }
- const apiUrl = `https://cmm.ai:8080/answer_with_token?token=${accessToken}&question=${input_text_value}`;
- axios.get(apiUrl, {
- cancelToken: source.token // 将取消令牌传递给 Axios 请求
- })
- .then(response => {
- apiHideLoading();
- console.log(response);
- // console.log(response.data.chart_info === undefined);
- if (response.data.chart_info === undefined) {
- console.log(response.data.data)
- alert(response.data.data)
- return
- } else {
- unit_value_box.style.display = "block";
- var chart_info = response.data.chart_info.Title;
- chartType = response.data.chart_info.Chart_type;
- var finance_img_url = response.data.imageUrl_info.imageUrl;
- if (response.data.imageUrl_info != null) {
- console.log(finance_img_url);
- document.getElementById('img_box_url').src = finance_img_url;
- }
- keywordInput.value = chart_info;
- chartTitle.textContent = chart_info;
- unit = response.data.chart_info.Unit_of_dependent_variable;
- var Label_dependent_variable = response.data.chart_info.Label_dependent_variable;
- var Label_independent_variable = response.data.chart_info.Label_independent_variable;
- stocknumber = response.data.chart_info.args;
- chartTypeBtn.value = chartType;
- 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;
- }
- obj.text = chartType;
- dataArray = response.data.data;
- if (chartType === "table") {
- unit_value.textContent = "";
- unit_value_box.style.display = "none"
- createTable(dataArray, unit, Label_dependent_variable, Label_independent_variable);
- // document.getElementById('img_box_url').src = "";
- } else if (chartType === "bar") {
- unit_value_box.style.display = 'block';
- console.log('圖表類型bar')
- $('#textToChart').hide();
- extractAndGenerateChart(dataArray);
- } else if (chartType === "doughnut") {
- unit_value.textContent = "";
- $('#textToChart').hide();
- unit_value_box.style.display = 'none';
- generatePieChart(dataArray, pieFontSize, PieMaxWidth)
- } else {
- unit_value_box.style.display = "block"
- $('#chartdiv').hide();
- generateChart(dataArray);
- }
- // }
- // 在這裡處理成功獲取 JSON 的情況
- // console.log(response);
- // switch (chartType) {
- // case "line":
- // document.getElementById("inlineRadio4").checked = true; // 折线图
- // break;
- // case "bar":
- // document.getElementById("inlineRadio5").checked = true; // 柱状图
- // labelDependent = response.data.chart_info.Label_dependent_variable;
- // break;
- // case "pie":
- // document.getElementById("inlineRadio6").checked = true; // 圆饼图
- // break;
- // case "table":
- // document.getElementById("inlineRadio7").checked = true; // 表格
- // break;
- // default:
- // // 默认情况
- }
- // generateChart(dataArray);
- })
- .catch(error => {
- // 错误处理逻辑,包括取消请求的情况
- apiHideLoading();
- if (axios.isCancel(error)) {
- console.log('请求被取消:', error.message);
- } else {
- console.error('发生错误:', error);
- }
- });
- }
- // 取消请求的函数
- function cancelRequest() {
- if (source) {
- source.cancel('取消了 API 请求');
- apiHideLoading(); // 隐藏加载状态
- }
- }
- document.getElementById('cancel_send_data').addEventListener('click', cancelRequest);
- $(document).ready(function () {
- $('#dataTable').DataTable();
- });
- function resizeChart() {
- console.log(myChart)
- if (myChart != null) {
- myChart.resize();
- }
- }
- document.addEventListener('visibilitychange', function () {
- console.log('Visibility changed:', document.visibilityState);
- if (document.visibilityState === 'visible') {
- resizeChart();
- }
- });
- // 监听窗口resize事件
- window.addEventListener('resize', resizeChart);
- var setting_button = document.getElementById('chart_seeting_button');
- var closeButton = document.getElementById('style_setting_close');
- var closeButton_table = document.getElementById('style_setting_close_table');
- // var borderSetting = document.getElementById('borderSetting');
- var lineChartSetting = document.getElementById('lineChartSetting');
- var barChartSetting = document.getElementById('barChartSetting');
- var table_setting = document.getElementById('table_setting');
- var chart_category = document.getElementById('chart_category');
- var pie_setting = document.getElementById('pie_setting');
- // 获取 chartDiv 元素
- setting_button.addEventListener('click', () => {
- console.log('setting_button')
- if (myChart === null && !chartJsBox.querySelector('table') && chartDiv.childElementCount === 0) {
- alert('請先生成圖表');
- return
- }
- if (chartType === 'table') {
- console.log('表格');
- sidebar.classList.toggle('show');
- sidebar.classList.toggle('hidden');
- barChartSetting.style.display = 'none';
- lineChartSetting.style.display = 'none';
- table_setting.style.display = 'block';
- chart_category.style.display = 'none';
- pie_setting.style.display = 'none';
- } else if (chartType === "bar") {
- console.log('柱狀圖')
- sidebar.classList.toggle('show');
- sidebar.classList.toggle('hidden');
- barChartSetting.style.display = 'block';
- lineChartSetting.style.display = 'none';
- table_setting.style.display = 'none';
- pie_setting.style.display = 'none';
- } else if (chartType === "doughnut") {
- console.log('快捷功能圓餅圖')
- sidebar.classList.toggle('show');
- sidebar.classList.toggle('hidden');
- barChartSetting.style.display = 'none';
- lineChartSetting.style.display = 'none';
- pie_setting.style.display = 'block';
- table_setting.style.display = 'none';
- chart_category.style.display = 'none';
- document.getElementById('unit_input').style.display = 'none';
- } else {
- sidebar.classList.toggle('show');
- sidebar.classList.toggle('hidden');
- table_setting.style.display = 'none';
- barChartSetting.style.display = 'none';
- lineChartSetting.style.display = 'block';
- pie_setting.style.display = 'none';
- }
- });
- closeButton.addEventListener('click', () => {
- sidebar.classList.remove('show');
- sidebar.classList.add('hidden');
- });
- const finance_options = [
- { name: "原油油桶", imageUrl: "./img/finance/01.webp" },
- { name: "黃金", imageUrl: "./img/finance/02.webp" },
- { name: "房屋", imageUrl: "./img/finance/03.webp" },
- { name: "車", imageUrl: "./img/finance/04.webp" },
- { name: "股市", imageUrl: "./img/finance/05.webp" },
- { name: "晶圓", imageUrl: "./img/finance/06.webp" },
- { name: "TSMC 台積電", imageUrl: "./img/finance/07.webp" },
- { name: "台幣", imageUrl: "./img/finance/08.webp" },
- { name: "美金", imageUrl: "./img/finance/09.webp" },
- { name: "購物車", imageUrl: "./img/finance/10.webp" },
- { name: "美中貿易", imageUrl: "./img/finance/11.webp" },
- { name: "世界地圖", imageUrl: "./img/finance/12.webp" },
- { name: "小麥", imageUrl: "./img/finance/13.webp" },
- { name: "玉米", imageUrl: "./img/finance/14.webp" },
- { name: "智慧產線", imageUrl: "./img/finance/15.webp" }
- ];
- const selectOptions = document.getElementById('finance_options');
- const selectOptions_table = document.getElementById('finance_options_table');
- finance_options.forEach((option, index) => {
- const optionElement = document.createElement('option');
- optionElement.value = index + 1; // 值从 1 开始
- optionElement.textContent = option.name;
- optionElement.setAttribute('data-image-url', option.imageUrl); // 存储图片 URL
- selectOptions.appendChild(optionElement);
- });
- selectOptions.addEventListener('change', function () {
- const selectedOption = selectOptions.options[selectOptions.selectedIndex];
- const imageUrl = selectedOption.getAttribute('data-image-url');
- document.getElementById('img_box_url').src = imageUrl;
- });
- // finance_options.forEach((option, index) => {
- // const optionElement = document.createElement('option');
- // optionElement.value = index + 1; // 值从 1 开始
- // optionElement.textContent = option.name;
- // optionElement.setAttribute('data-image-url', option.imageUrl); // 存储图片 URL
- // selectOptions_table.appendChild(optionElement);
- // });
- // selectOptions_table.addEventListener('change', function () {
- // const selectedOption = selectOptions_table.options[selectOptions_table.selectedIndex];
- // const imageUrl = selectedOption.getAttribute('data-image-url');
- // document.getElementById('img_box_url').src = imageUrl;
- // });
- document.querySelectorAll('input[name="ChartOptions"]').forEach(function (radio) {
- radio.addEventListener('change', function () {
- // 檢查哪個單選按鈕被選中
- if (this.value === 'line') {
- // 如果選擇了折線圖,執行相應的操作
- console.log("選擇了折線圖");
- // 在這裡執行顯示折線圖的相關代碼
- } else if (this.value === 'doughnut') {
- // 如果選擇了柱狀圖,執行相應的操作
- console.log("選擇了柱狀圖");
- // 在這裡執行顯示柱狀圖的相關代碼
- }
- });
- });
- function tokencheck() {
- if (!localStorage.getItem("access_token")) {
- window.location.href = "./login.html";
- } else {
- console.log("存在");
- }
- }
- tokencheck();
- function logout() {
- localStorage.removeItem("access_token");
- }
- $(document).on("click", "#logout", function (event) {
- alert("登出成功");
- logout();
- location.reload();
- });
- // speech_to_text
- var closeRecord = document.getElementById('recording_block_close');
- var recording_block = document.getElementById('recording_block');
- var PageLM = "2024-05-07 18:33";
- var recording_button = document.getElementById('recording_button');
- var stopButton = document.getElementById('stop');
- var audio = document.getElementById('audio');
- var recorder, audioBlob;
- closeRecord.addEventListener('click', () => {
- recPause();
- console.log('record-click')
- recording_block.classList.remove('show');
- recording_block.classList.add('hidden');
- });
- function reclog(s, color) {
- var now = new Date();
- var t = ("0" + now.getHours()).substr(-2)
- + ":" + ("0" + now.getMinutes()).substr(-2)
- + ":" + ("0" + now.getSeconds()).substr(-2);
- var div = document.createElement("div");
- var elem = document.querySelector(".reclog");
- elem.insertBefore(div, elem.firstChild);
- div.innerHTML = '<div style="color:' + (!color ? "" : color == 1 ? "red" : color == 2 ? "#0b1" : color) + '">[' + t + ']' + s + '</div>';
- };
- window.onerror = function (message, url, lineNo, columnNo, error) {
- //https://www.cnblogs.com/xianyulaodi/p/6201829.html
- reclog('<span style="color:red">【Uncaught Error】' + message + '<pre>' + "at:" + lineNo + ":" + columnNo + " url:" + url + "\n" + (error && error.stack || Html_$T("kBaF::不能获得错误堆栈")) + '</pre></span>');
- };
- if (!window.Html_$T) {//没有提供本页面用的国际化多语言支持时 返回中文文本
- window.Html_$T = function () {
- var a = arguments, txt = a[0].replace(/^.+?::/, ""), n = 0;
- for (var i = 0; i < a.length; i++) { if (typeof a[i] == "number") { n = i; break } }
- txt = txt.replace(/\{(\d+)\}/g, function (v, f) { v = a[+f + n]; return v == null ? "" : v });
- return txt;
- }
- window.Html_xT = function (v) { return v }
- }
- if (window.Recorder) {
- // reclog(Html_$T('BL9u::頁面已準備好,請先點擊打開錄音,然後點擊錄製'), 2);
- alert('錄音已準備好,請先點擊右下角打開錄音,即可開始錄製')
- } else {
- reclog(Html_$T("YzPd::js文件加载失败,请刷新重试!"), "#f00;font-size:50px");
- console.log('js文件加载失敗,请刷新重试!')
- }
- recording_button.addEventListener('click', async () => {
- recording_block.classList.toggle('show');
- recording_block.classList.toggle('hidden');
- recStart();
- });
- function recStart() {//打开了录音后才能进行start、stop调用
- rec.start();
- };
- stopButton.addEventListener('click', async () => {
- // recorder.stop();
- // uploadAudio(audioBlob);
- recStop();
- });
- window.onload = function () {
- recOpen();
- };
- // 錄音程式
- // =======================
- var rec, wave, recBlob;
- /**调用open打开录音请求好录音权限 Call open to open the recording and request the recording permission**/
- var recOpen = function () {//一般在显示出录音按钮或相关的录音界面时进行此方法调用,后面用户点击开始录音时就能畅通无阻了
- rec = null;
- wave = null;
- recBlob = null;
- var newRec = Recorder({
- type: "mp3", sampleRate: 16000, bitRate: 16 //mp3格式,指定采样率hz、比特率kbps,其他参数使用默认配置;注意:是数字的参数必须提供数字,不要用字符串;需要使用的type类型,需提前把格式支持文件加载进来,比如使用wav格式需要提前加载wav.js编码引擎
- , onProcess: function (buffers, powerLevel, bufferDuration, bufferSampleRate, newBufferIdx, asyncEnd) {
- // // //录音实时回调,大约1秒调用12次本回调
- document.querySelector(".recpowerx").style.width = powerLevel + "%";
- document.querySelector(".recpowert").innerText = formatMs(bufferDuration, 1) + " / " + powerLevel;
- // //可视化图形绘制
- // wave.input(buffers[buffers.length - 1], powerLevel, bufferSampleRate);
- }
- });
- newRec.open(function () {//打开麦克风授权获得相关资源
- rec = newRec;
- //此处创建这些音频可视化图形绘制浏览器支持妥妥的
- // wave = Recorder.FrequencyHistogramView({ elem: ".recwave" });
- reclog(Html_$T("GVCa::已打開錄音,可以點擊錄制開始錄音"), 2);
- }, function (msg, isUserNotAllow) {//用户拒绝未授权或不支持
- reclog((isUserNotAllow ? "UserNotAllow, " : "") + Html_$T("TOOV::打開錄音失敗:") + msg, 1);
- });
- };
- /**关闭录音,释放资源 Close recording, release resources**/
- function recClose() {
- if (rec) {
- rec.close();
- reclog(Html_$T("jqOs::已关闭"));
- } else {
- reclog(Html_$T("VOOw::未打开录音"), 1);
- };
- };
- /**开始录音 Start recording**/
- function recStart() {//打开了录音后才能进行start、stop调用
- if (rec && Recorder.IsOpen()) {
- recBlob = null;
- rec.start();
- reclog(Html_$T("CGdy::已經開始錄音...") + " " + rec.set.type + " " + rec.set.sampleRate + " " + rec.set.bitRate + "kbps");
- } else {
- reclog(Html_$T("ajKR::未打开錄音"), 1);
- };
- };
- /**暂停录音 Passing recording**/
- function recPause() {
- if (rec && Recorder.IsOpen()) {
- rec.pause();
- reclog(Html_$T("GvCy::已暂停"));
- } else {
- reclog(Html_$T("gCAR::未打開錄音"), 1);
- };
- };
- /**恢复录音 Resume recording**/
- function recResume() {
- if (rec && Recorder.IsOpen()) {
- rec.resume();
- reclog(Html_$T("5q1K::继续录音中..."));
- } else {
- reclog(Html_$T("Ob6S::未打开录音"), 1);
- };
- };
- /**结束录音,得到音频文件 Stop recording and get audio files**/
- function recStop() {
- if (!(rec && Recorder.IsOpen())) {
- reclog(Html_$T("5JuL::未打開錄音"), 1);
- return;
- };
- rec.stop(function (blob, duration) {
- console.log(blob, (window.URL || webkitURL).createObjectURL(blob), Html_xT(Html_$T("gOix::時長:{1}ms", 0, duration)));
- recBlob = blob;
- var file = new File([blob], "recording.mp3", { type: "audio/mp3" });
- // console.log(file);
- handleAudioToText(file);
- reclog(Html_$T("0LHf::已錄製mp3:{1}ms {2}字節,可以點擊播放、上傳、本地下载了", 0, formatMs(duration), blob.size), 2);
- }, function (msg) {
- reclog(Html_$T("kGZO::錄音失敗:") + msg, 1);
- });
- };
- /**播放 Play**/
- function recPlay() {
- if (!recBlob) {
- reclog(Html_$T("tIke::请先錄音,然后停止後再播放"), 1);
- return;
- };
- var cls = ("a" + Math.random()).replace(".", "");
- reclog(Html_$T('GlWb::播放中: ') + '<span class="' + cls + '"></span>');
- var audio = document.createElement("audio");
- audio.controls = true;
- document.querySelector("." + cls).appendChild(audio);
- //简单利用URL生成播放地址,注意不用了时需要revokeObjectURL,否则霸占内存
- audio.src = (window.URL || webkitURL).createObjectURL(recBlob);
- audio.play();
- setTimeout(function () {
- (window.URL || webkitURL).revokeObjectURL(audio.src);
- }, 5000);
- };
- /**上传 Upload**/
- function recUpload() {
- var blob = recBlob;
- if (!blob) {
- reclog(Html_$T("DUTn::请先录音,然后停止后再上传"), 1);
- return;
- };
- //本例子假设使用原始XMLHttpRequest请求方式,实际使用中自行调整为自己的请求方式
- //录音结束时拿到了blob文件对象,可以用FileReader读取出内容,或者用FormData上传
- var api = "http://127.0.0.1:9528";
- var onreadystatechange = function (xhr, title) {
- return function () {
- if (xhr.readyState == 4) {
- if (xhr.status == 200) {
- reclog(title + Html_$T("G2MU::上传成功") + ' <span style="color:#999">response: ' + xhr.responseText + '</span>', 2);
- } else {
- reclog(title + Html_$T("TUdi::没有完成上传,演示上传地址无需关注上传结果,只要浏览器控制台内Network面板内看到的请求数据结构是预期的就ok了。"), "#d8c1a0");
- console.error(Html_xT(title + Html_$T("HjDi::上传失败")), xhr.status, xhr.responseText);
- };
- };
- };
- };
- reclog(Html_$T("QnSI::开始上传到{1},请稍候... (你可以先到源码 /assets/node-localServer 目录内执行 npm run start 来运行本地测试服务器)", 0, api));
- /***方式一:将blob文件转成base64纯文本编码,使用普通application/x-www-form-urlencoded表单上传***/
- var reader = new FileReader();
- reader.onloadend = function () {
- var postData = "";
- postData += "mime=" + encodeURIComponent(blob.type);//告诉后端,这个录音是什么格式的,可能前后端都固定的mp3可以不用写
- postData += "&upfile_b64=" + encodeURIComponent((/.+;\s*base64\s*,\s*(.+)$/i.exec(reader.result) || [])[1]) //录音文件内容,后端进行base64解码成二进制
- //...其他表单参数
- var xhr = new XMLHttpRequest();
- xhr.open("POST", api + "/uploadBase64");
- xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
- xhr.onreadystatechange = onreadystatechange(xhr, Html_$T("gG1f::上传方式一【Base64】"));
- xhr.send(postData);
- };
- reader.readAsDataURL(blob);
- /***方式二:使用FormData用multipart/form-data表单上传文件***/
- var form = new FormData();
- form.append("upfile", blob, "recorder.mp3"); //和普通form表单并无二致,后端接收到upfile参数的文件,文件名为recorder.mp3
- //...其他表单参数
- var xhr = new XMLHttpRequest();
- xhr.open("POST", api + "/upload");
- xhr.onreadystatechange = onreadystatechange(xhr, Html_$T("vDzB::上传方式二【FormData】"));
- xhr.send(form);
- };
- /**本地下载 Local download**/
- function recLocalDown() {
- if (!recBlob) {
- reclog(Html_$T("M86h::请先录音,然后停止后再下载"), 1);
- return;
- };
- var cls = ("a" + Math.random()).replace(".", "");
- recdown64.lastCls = cls;
- reclog(Html_$T('vJPl::点击 ') + '<span class="' + cls + '"></span>' + Html_$T('Whtc:: 下载,或复制文本')
- + '<button onclick="recdown64(\'' + cls + '\')">' + Html_$T('XK4l::生成Base64文本') + '</button><span class="' + cls + '_b64"></span>');
- var fileName = "recorder-" + Date.now() + ".mp3";
- var downA = document.createElement("A");
- downA.innerHTML = Html_$T("g8Fy::下载 ") + fileName;
- downA.href = (window.URL || webkitURL).createObjectURL(recBlob);
- downA.download = fileName;
- document.querySelector("." + cls).appendChild(downA);
- if (/mobile/i.test(navigator.userAgent)) {
- alert(Html_xT(Html_$T("DIEK::因移动端绝大部分国产浏览器未适配Blob Url的下载,所以本demo代码在移动端未调用downA.click()。请尝试点击日志中显示的下载链接下载")));
- } else {
- downA.click();
- }
- //不用了时需要revokeObjectURL,否则霸占内存
- //(window.URL||webkitURL).revokeObjectURL(downA.href);
- };
- function recdown64(cls) {
- var el = document.querySelector("." + cls + "_b64");
- if (recdown64.lastCls != cls) {
- el.innerHTML = '<span style="color:red">' + Html_$T("eKKx::老的数据没有保存,只支持最新的一条") + '</span>';
- return;
- }
- var reader = new FileReader();
- reader.onloadend = function () {
- el.innerHTML = '<textarea></textarea>';
- el.querySelector("textarea").value = reader.result;
- };
- reader.readAsDataURL(recBlob);
- };
- var formatMs = function (ms, all) {
- var ss = ms % 1000; ms = (ms - ss) / 1000;
- var s = ms % 60; ms = (ms - s) / 60;
- var m = ms % 60; ms = (ms - m) / 60;
- var h = ms;
- var t = (h ? h + ":" : "")
- + (all || h + m ? ("0" + m).substr(-2) + ":" : "")
- + (all || h + m + s ? ("0" + s).substr(-2) + "″" : "")
- + ("00" + ss).substr(-3);
- return t;
- };
- // =======================
- let mediaRecorder;
- let audioChunks = [];
- var recordText = document.getElementById('record_text');
- async function handleAudioToText(file) {
- console.log('tts')
- let audioLang = "cmn-Hant-TW"; // 音訊語言
- // let lang = localStorage.getItem("lang");
- let lang = "zh-tw";
- console.log("lang", lang);
- switch (lang) {
- case "zh-tw":
- audioLang = "cmn-Hant-TW";
- break;
- case "en-us":
- audioLang = "en-US";
- break;
- case "ja-jp":
- audioLang = "ja-JP";
- break;
- case "ko-kr":
- audioLang = "ko-KR";
- break;
- default:
- break;
- }
- let url = `https://cmm.ai:9001/gcp/speech-to-text?language_code=${audioLang}`;
- const formData = new FormData();
- formData.append("file", file);
- try {
- const response = await axios.post(url, formData);
- console.log("response", response);
- input_text_value = response.data;
- recording_block.classList.remove('show');
- recording_block.classList.add('hidden');
- if (input_text_value.length === 0) {
- alert('請再說一次')
- return
- }
- console.log(input_text_value[0]);
- inputField.value = input_text_value[0];
- // Show the result for a short time before executing get_data
- get_data(input_text_value);
- // get_data(input_text_value);
- } catch (error) {
- console.log("error", error);
- }
- }
- Object.defineProperty(obj, 'text', {
- get() {
- return this._text;
- },
- set(newValue) {
- console.log(`字符串从 "${this._text}" 变为 "${newValue}"`);
- this._text = newValue;
- }
- });
- // sendButtonClickHandler(input_text_value);
|