new
This commit is contained in:
parent
f65ab820c1
commit
c23b6ca0cb
Binary file not shown.
Binary file not shown.
36
app.py
36
app.py
@ -1,6 +1,7 @@
|
||||
from flask import Flask, render_template, jsonify, request
|
||||
import json
|
||||
import os
|
||||
import requests
|
||||
from model_connector import ModelConnector
|
||||
from dax_parser import DaxParser
|
||||
|
||||
@ -56,6 +57,41 @@ def get_call_graph():
|
||||
except Exception as e:
|
||||
return jsonify({'success': False, 'message': str(e)})
|
||||
|
||||
@app.route('/format_dax', methods=['POST'])
|
||||
def format_dax():
|
||||
"""Proxy for DAX formatter service."""
|
||||
try:
|
||||
dax_code = request.json.get('daxCode')
|
||||
if not dax_code:
|
||||
return jsonify({'success': False, 'message': 'No DAX code provided'})
|
||||
|
||||
# 调用新的DAX格式化API
|
||||
payload = {
|
||||
'dax': dax_code,
|
||||
'callerApp': 'https://www.daxformatter.com/',
|
||||
'callerVersion': '0.5.3',
|
||||
'listSeparator': ',',
|
||||
'decimalSeparator': '.',
|
||||
'maxLineLength': 0
|
||||
}
|
||||
|
||||
response = requests.post('https://daxformatter.azurewebsites.net/api/DaxTokenFormat/',
|
||||
json=payload)
|
||||
|
||||
if response.status_code != 200:
|
||||
return jsonify({'success': False, 'message': 'DAX formatting service error'})
|
||||
|
||||
# 解析返回的JSON
|
||||
formatted_data = response.json()
|
||||
|
||||
# 检查是否有错误
|
||||
if formatted_data.get('errors') and len(formatted_data['errors']) > 0:
|
||||
return jsonify({'success': False, 'message': 'DAX formatting error: ' + str(formatted_data['errors'])})
|
||||
|
||||
return jsonify({'success': True, 'formattedTokens': formatted_data['formatted']})
|
||||
except Exception as e:
|
||||
return jsonify({'success': False, 'message': str(e)})
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.run(debug=True)
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
from sys import path
|
||||
path.append('C:\\Users\\ChenwuServise\\OneDrive - AZCollaboration\\Desktop\\GIT\\PBI-Measure-CallGraph\\MSNET')
|
||||
path.append('C:\\Users\\Chenw\\Documents\\Trae\\PBI-Measure-CallGraph\\MSNET')
|
||||
|
||||
import pyadomd
|
||||
import pandas as pd
|
||||
|
@ -1,3 +1,5 @@
|
||||
Flask==2.3.3
|
||||
pyodbc==4.0.39
|
||||
pandas==2.2.3
|
||||
requests==2.31.0
|
||||
beautifulsoup4==4.12.2
|
||||
|
41
static/css/dax-highlight.css
Normal file
41
static/css/dax-highlight.css
Normal file
@ -0,0 +1,41 @@
|
||||
/* DAX语法高亮样式 */
|
||||
#measure-expression {
|
||||
font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
|
||||
background-color: #f8f8f8;
|
||||
padding: 10px;
|
||||
border-radius: 4px;
|
||||
overflow: auto;
|
||||
line-height: 1.5;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
/* 关键字 */
|
||||
.dax-keyword {
|
||||
color: #0000ff;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* 函数 */
|
||||
.dax-function {
|
||||
color: #795e26;
|
||||
}
|
||||
|
||||
/* 括号 */
|
||||
.dax-parenthesis {
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
/* 数字 */
|
||||
.dax-number {
|
||||
color: #098658;
|
||||
}
|
||||
|
||||
/* 字符串 */
|
||||
.dax-string {
|
||||
color: #a31515;
|
||||
}
|
||||
|
||||
/* 普通文本 */
|
||||
.dax-normal {
|
||||
color: #000000;
|
||||
}
|
@ -5,6 +5,8 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Power BI Measure Call Graph</title>
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/dax-highlight.css') }}">
|
||||
|
||||
<!-- D3.js for visualization -->
|
||||
<script src="https://d3js.org/d3.v7.min.js"></script>
|
||||
<script>
|
||||
@ -13,31 +15,85 @@
|
||||
const daxCode = measureExpression.textContent;
|
||||
|
||||
try {
|
||||
const formData = new FormData();
|
||||
formData.append('fx', daxCode);
|
||||
formData.append('r', 'US');
|
||||
|
||||
const response = await fetch('https://www.daxformatter.com', {
|
||||
// 调用后端API进行格式化
|
||||
const response = await fetch('/format_dax', {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({ daxCode: daxCode })
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error('格式化请求失败');
|
||||
}
|
||||
|
||||
const result = await response.text();
|
||||
// 解析返回的HTML,提取格式化后的DAX代码
|
||||
const parser = new DOMParser();
|
||||
const doc = parser.parseFromString(result, 'text/html');
|
||||
const formattedDax = doc.querySelector('#formatted-dax').textContent;
|
||||
const result = await response.json();
|
||||
|
||||
measureExpression.textContent = formattedDax;
|
||||
if (!result.success) {
|
||||
throw new Error(result.message || '格式化失败');
|
||||
}
|
||||
|
||||
// 处理新的格式化结果(带有标记类型的数组)
|
||||
const formattedHtml = applyDaxSyntaxHighlighting(result.formattedTokens);
|
||||
measureExpression.innerHTML = formattedHtml;
|
||||
} catch (error) {
|
||||
console.error('格式化DAX时出错:', error);
|
||||
alert('格式化DAX时出错,请检查网络连接或稍后重试');
|
||||
}
|
||||
}
|
||||
|
||||
// 将格式化的DAX标记转换为HTML并应用语法高亮
|
||||
function applyDaxSyntaxHighlighting(formattedTokens) {
|
||||
if (!formattedTokens || formattedTokens.length === 0) {
|
||||
return '';
|
||||
}
|
||||
|
||||
let html = '';
|
||||
|
||||
// 处理每一行的标记
|
||||
formattedTokens.forEach(line => {
|
||||
line.forEach(token => {
|
||||
const text = token.string;
|
||||
const type = token.type || 'Normal';
|
||||
|
||||
// 根据标记类型应用不同的CSS类
|
||||
switch(type) {
|
||||
case 'Keyword':
|
||||
html += `<span class="dax-keyword">${escapeHtml(text)}</span>`;
|
||||
break;
|
||||
case 'Function':
|
||||
html += `<span class="dax-function">${escapeHtml(text)}</span>`;
|
||||
break;
|
||||
case 'Parenthesis':
|
||||
html += `<span class="dax-parenthesis">${escapeHtml(text)}</span>`;
|
||||
break;
|
||||
case 'Number':
|
||||
html += `<span class="dax-number">${escapeHtml(text)}</span>`;
|
||||
break;
|
||||
case 'String':
|
||||
html += `<span class="dax-string">${escapeHtml(text)}</span>`;
|
||||
break;
|
||||
default:
|
||||
html += escapeHtml(text);
|
||||
}
|
||||
});
|
||||
html += '\n'; // 添加换行
|
||||
});
|
||||
|
||||
return html;
|
||||
}
|
||||
|
||||
// 转义HTML特殊字符
|
||||
function escapeHtml(text) {
|
||||
return text
|
||||
.replace(/&/g, "&")
|
||||
.replace(/</g, "<")
|
||||
.replace(/>/g, ">")
|
||||
.replace(/"/g, """)
|
||||
.replace(/'/g, "'");
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
Loading…
Reference in New Issue
Block a user