index.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494
  1. <template>
  2. <div class="query-index">
  3. <div class="query-index-tree" v-if="showTree">
  4. <div class="query-index-tree-search">
  5. <a-input-search
  6. v-model:value="subjectTrees.searchStr"
  7. placeholder="主题名称关键字..."
  8. @search="getSubjectTree"
  9. />
  10. <DoubleLeftOutlined @click="showTree=false"/>
  11. </div>
  12. <div class="query-index-tree-box">
  13. <a-tree
  14. :show-line="true"
  15. v-model:expandedKeys="subjectTrees.expandedKeys"
  16. :tree-data="subjectTrees.data"
  17. @expand="treeOnExpand">
  18. <template
  19. #title="{ title, key, subId, fieldCode, fieldId, fieldName, fieldAlias, dataType, subjectName, queryTypeId, dictionaryCode }">
  20. <div v-if="(fieldAlias)" class="query-index-tree-item"
  21. draggable="true"
  22. @dragstart="onDragStart($event,{subId, fieldCode, fieldId, fieldName, fieldAlias, dataType, subjectName, queryType:queryTypeId, dictionaryCode})"
  23. >{{ title }}
  24. </div>
  25. <div v-else class="query-index-tree-item">{{ title }}</div>
  26. </template>
  27. </a-tree>
  28. </div>
  29. </div>
  30. <div class="query-index-close" v-else>
  31. <DoubleRightOutlined @click="showTree=true"/>
  32. </div>
  33. <div class="query-index-content">
  34. <div class="query-index-form">
  35. <a-form ref="formRef" name="fromQuery"
  36. class="ant-advanced-search-form"
  37. :label-col="labelCol"
  38. :model="formState.temp">
  39. <a-row :gutter="24" class="query-index-row">
  40. <a-col :span="6">
  41. <a-form-item name="tempName"
  42. :rules="[{ required: true, message: '请输入模板名称!' }]">
  43. <template #label>
  44. <span>模板名称</span>
  45. </template>
  46. <a-input v-model:value="formState.temp.tempName" placeholder="..."/>
  47. </a-form-item>
  48. </a-col>
  49. <a-col :span="6">
  50. <a-form-item name="tempNo"
  51. :rules="[{ required: true, message: '请输入模板编号!' }]">
  52. <template #label>
  53. <span>模板编号</span>
  54. </template>
  55. <a-input v-model:value="formState.temp.tempNo" placeholder="..."/>
  56. </a-form-item>
  57. </a-col>
  58. <a-col :span="6">
  59. <a-form-item name="tempName"
  60. :rules="[{ required: true, message: '至少选择一个主题字段!' }]">
  61. <template #label>
  62. <span>主题</span>
  63. </template>
  64. <a-input v-model:value="formState.sub.subjectName" placeholder="..." disabled="true"/>
  65. </a-form-item>
  66. </a-col>
  67. <a-col :span="6" style="text-align: left">
  68. <a-button type="primary" html-type="submit" @click="getQuery">查询预览</a-button>
  69. <a-button html-type="submit" @click="onFinish" style="margin-left: 10px;">保存模板</a-button>
  70. </a-col>
  71. <a-col :span="18">
  72. <a-form-item name="remark">
  73. <template #label>
  74. <span>备注</span>
  75. </template>
  76. <a-input v-model:value="formState.temp.remark" placeholder="..."/>
  77. </a-form-item>
  78. </a-col>
  79. <a-col :span="6" style="text-align: left">
  80. <a-button type="primary" html-type="submit" @click="getExcel">导出测试</a-button>
  81. </a-col>
  82. <a-col :span="24">
  83. <a-form-item>
  84. <template #label>
  85. <SearchOutlined style="color: #8DC6F9;"/>
  86. <span>筛选</span>
  87. </template>
  88. <DragWhere ref="where" @change="onChangeWhere" query-type="where"
  89. :subjectId="formState.temp.subId"></DragWhere>
  90. </a-form-item>
  91. </a-col>
  92. <a-col :span="24">
  93. <a-form-item>
  94. <template #label>
  95. <ColumnHeightOutlined style="color: #8DC6F9;"/>
  96. <span>维度</span>
  97. </template>
  98. <DragBase ref="base" @change="onChangeBase" :subjectId="formState.temp.subId"></DragBase>
  99. </a-form-item>
  100. </a-col>
  101. <a-col :span="24">
  102. <a-form-item>
  103. <template #label>
  104. <ColumnWidthOutlined style="color: #8DC6F9;"/>
  105. <span>度量</span>
  106. </template>
  107. <DragMeasure ref="measure" @change="onChangeMeasure" query-type="measure"
  108. :subjectId="formState.temp.subId"></DragMeasure>
  109. </a-form-item>
  110. </a-col>
  111. </a-row>
  112. </a-form>
  113. </div>
  114. <div class="query-index-table">
  115. <a-tabs v-model:activeKey="activeTab" class="query-index-tabs" @change="tabChange">
  116. <a-tab-pane key="1" tab="列表视图">
  117. <DisplayTable ref="display" :bases="formState.bases" :measures="formState.measures"
  118. @displayChange="onDisplayChange"></DisplayTable>
  119. </a-tab-pane>
  120. <a-tab-pane key="2" tab="柱状图" forceRender="true" style="width: 100%;">
  121. <DisplayChartBar ref="displayChartBar" :bases="formState.bases"
  122. :measures="formState.measures"></DisplayChartBar>
  123. </a-tab-pane>
  124. <a-tab-pane key="3" tab="曲线图" forceRender="true" style="width: 100%;">
  125. <DisplayChartLine ref="displayChartLine" :bases="formState.bases"
  126. :measures="formState.measures"></DisplayChartLine>
  127. </a-tab-pane>
  128. <a-tab-pane key="4" tab="条形图" forceRender="true" style="width: 100%;">
  129. <DisplayChartYbar ref="displayChartYbar" :bases="formState.bases"
  130. :measures="formState.measures"></DisplayChartYbar>
  131. </a-tab-pane>
  132. </a-tabs>
  133. </div>
  134. </div>
  135. <ExportData ref="exportData"></ExportData>
  136. <a-modal v-model:visible="modal.open" title="生成Sql语句成功,调试窗口" width="60%">
  137. <a-textarea v-model:value="modal.sqlString" placeholder="Basic usage" :rows="20"/>
  138. <template #footer></template>
  139. </a-modal>
  140. </div>
  141. </template>
  142. <script lang="ts">
  143. import {ref, defineComponent} from 'vue';
  144. import type {FormInstance} from 'ant-design-vue';
  145. import {useRoute} from 'vue-router';
  146. import DragWhere from '@/components/basic/query/drag-where.vue'
  147. import DragBase from '@/components/basic/query/drag-base.vue'
  148. import DragMeasure from '@/components/basic/query/drag-measure.vue'
  149. import DisplayTable from '@/components/basic/query/display-table.vue'
  150. import DisplayChartBar from '@/components/basic/query/display-chart-bar.vue'
  151. import DisplayChartYbar from '@/components/basic/query/display-chart-ybar.vue'
  152. import DisplayChartLine from '@/components/basic/query/display-chart-line.vue'
  153. import ExportData from '@/components/basic/query/export-data.vue'
  154. import {save, get, postData} from "@/api/common";
  155. import type {TreeProps} from 'ant-design-vue';
  156. export default defineComponent({
  157. name: 'queryindex',
  158. components: {
  159. DragWhere, DragBase, DragMeasure, DisplayTable,
  160. DisplayChartBar, DisplayChartLine, DisplayChartYbar, ExportData
  161. },
  162. setup() {
  163. const route = useRoute();
  164. const expand = ref(false);
  165. const formRef = ref<FormInstance>();
  166. const measure = ref<typeof DragMeasure>();
  167. const base = ref<typeof DragBase>();
  168. const where = ref<typeof DragWhere>();
  169. const display = ref<typeof DisplayTable>();
  170. const displayChartBar = ref<typeof DisplayChartBar>();
  171. const displayChartLine = ref<typeof DisplayChartLine>();
  172. const displayChartYbar = ref<typeof DisplayChartYbar>();
  173. const exportData = ref<typeof ExportData>();
  174. const activeTab = ref('1');
  175. const showTree = ref(true);
  176. const subjectTrees = ref({
  177. data: [] as TreeProps['treeData'],
  178. expandedKeys: [''],
  179. searchStr: ''
  180. });
  181. const formState = ref({
  182. temp: {
  183. tempId: '',
  184. tempName: '',
  185. tempNo: '',
  186. subId: null,
  187. remark: '',
  188. },
  189. sub: {
  190. subId: null,
  191. subjectName: '',
  192. },
  193. measures: [],
  194. wheres: [],
  195. bases: [],
  196. pagination: null
  197. });
  198. const modal = ref({
  199. open: false,
  200. sqlString: null
  201. });
  202. const tabChange = (key) => {
  203. console.log("tabChange", key);
  204. if (key == "2") {
  205. setTimeout(function () {
  206. (displayChartBar.value as any).resize();
  207. }, 100);
  208. }
  209. if (key == "3") {
  210. setTimeout(function () {
  211. (displayChartLine.value as any).resize();
  212. }, 100);
  213. }
  214. if (key == "4") {
  215. setTimeout(function () {
  216. (displayChartYbar.value as any).resize();
  217. }, 100);
  218. }
  219. }
  220. const onFinish = () => {
  221. if (formRef.value == undefined) {
  222. return;
  223. }
  224. formRef.value.validate().then(() => {
  225. save('temp/save', formStateGet()).then(result => {
  226. console.log(result);
  227. getTemp(result["tempId"]);
  228. });
  229. });
  230. }
  231. const getExcel = async () => {
  232. if (formState.value.temp.tempId && formState.value.temp.tempId.length > 0) {
  233. (exportData.value as any).doExport(formState.value.temp.tempId);
  234. }
  235. }
  236. const formStateGet = () => {
  237. formState.value.measures = (measure.value as any).getTagList();
  238. formState.value.wheres = (where.value as any).getTagList();
  239. formState.value.bases = (base.value as any).getTagList();
  240. //从视图取得翻页数据
  241. formState.value.pagination = (display.value as any).getPagination();
  242. console.log("formState", formState.value);
  243. return formState.value;
  244. };
  245. const getQuery = () => {
  246. postData('temp/genQuery', formStateGet()).then(result => {
  247. console.log(result);
  248. if (result["code"] != 0) {
  249. modal.value.open = true;
  250. modal.value.sqlString = result["sqlString"];
  251. }
  252. //将数据给视图,视图组装并显示
  253. (display.value as any).setData(result);
  254. (displayChartBar.value as any).setData(result);
  255. (displayChartLine.value as any).setData(result);
  256. (displayChartYbar.value as any).setData(result);
  257. });
  258. }
  259. const onDragStart = (event, obj) => {
  260. event.dataTransfer.setData("dragData", "-");
  261. obj.tempFeildId = new Date().getTime() + '';
  262. window["dragData"] = obj;
  263. console.log("onDragStart", obj);
  264. }
  265. const getSubjectTree = async function () {
  266. //loading.value = true;
  267. subjectTrees.value.data = await get('temp/getSubjectTree', {tabName: subjectTrees.value.searchStr});
  268. //计算第一个展开节点
  269. subjectTrees.value.expandedKeys = [];
  270. if (subjectTrees.value.data && subjectTrees.value.data.length > 0) {
  271. subjectTrees.value.expandedKeys.push(subjectTrees.value.data[0].key + "");
  272. subjectTrees.value.data[0].children?.forEach((it) => {
  273. subjectTrees.value.expandedKeys.push(it.key + "");
  274. });
  275. }
  276. console.log("getSubjectTree", subjectTrees.value, subjectTrees.value.expandedKeys);
  277. }
  278. getSubjectTree();
  279. const treeOnExpand = function (eKeys, args) {
  280. console.log(eKeys, args);
  281. if (args.node.parent == undefined) {
  282. subjectTrees.value.expandedKeys = [args.node.key];
  283. }
  284. }
  285. const getTemp = async function (tempId) {
  286. const rtn = await get('temp/get', {tempId: tempId});
  287. console.log(rtn);
  288. formState.value.temp = rtn.temp;
  289. formState.value.sub = rtn.sub;
  290. formState.value.bases = rtn.bases;
  291. formState.value.wheres = rtn.wheres;
  292. formState.value.measures = rtn.measures;
  293. setTimeout(displayReader, 100);
  294. (measure.value as any).setTagList(rtn.measures);
  295. (where.value as any).setTagList(rtn.wheres);
  296. (base.value as any).setTagList(rtn.bases);
  297. subjectTrees.value.expandedKeys = [];
  298. subjectTrees.value.expandedKeys.push(rtn.sub.subId);
  299. }
  300. const onChangeMeasure = (list, obj) => {
  301. console.log("onChangeMeasure", arguments, list, obj);
  302. formState.value.measures = list;
  303. displayReader();
  304. checkSubjectId(obj);
  305. }
  306. const onChangeWhere = (list, obj) => {
  307. console.log("onChangeWhere", arguments, list, obj);
  308. formState.value.wheres = list;
  309. displayReader();
  310. checkSubjectId(obj);
  311. }
  312. const onChangeBase = (list, obj) => {
  313. console.log("onChangeBase", arguments, list, obj);
  314. formState.value.bases = list;
  315. displayReader();
  316. checkSubjectId(obj);
  317. }
  318. const onDisplayChange = (pagination) => {
  319. //视图发起数据查询,如翻页
  320. console.log("onDisplayChange", pagination);
  321. formState.value.pagination = pagination;
  322. getQuery();
  323. }
  324. function displayReader() {
  325. //初始化视图显示
  326. console.log("displayReader", display.value);
  327. console.log("displayReader", display.value, displayChartBar.value);
  328. (display.value as any).reader();
  329. (displayChartBar.value as any).reader();
  330. (displayChartLine.value as any).reader();
  331. (displayChartYbar.value as any).reader();
  332. }
  333. const checkSubjectId = (obj) => {
  334. if (formState.value.temp.subId == null && obj != null) {
  335. formState.value.temp.subId = obj.subId;
  336. formState.value.sub.subId = obj.subId;
  337. formState.value.sub.subjectName = obj.subjectName;
  338. }
  339. if (formState.value.bases.length + formState.value.measures.length + formState.value.wheres.length <= 0) {
  340. formState.value.temp.subId = null;
  341. formState.value.sub.subId = null;
  342. formState.value.sub.subjectName = '';
  343. }
  344. console.log("formState.value.temp.subId", formState.value.temp.subId)
  345. }
  346. const labelCol = {style: {width: '100px'}};
  347. return {
  348. route,
  349. expand,
  350. showTree,
  351. onFinish,
  352. formRef,
  353. formState,
  354. labelCol,
  355. measure,
  356. where,
  357. base,
  358. activeTab,
  359. display,
  360. displayChartBar,
  361. displayChartLine,
  362. displayChartYbar,
  363. tabChange,
  364. onChangeMeasure,
  365. onChangeWhere,
  366. onChangeBase,
  367. onDragStart,
  368. checkSubjectId,
  369. getQuery,
  370. getTemp,
  371. getExcel,
  372. exportData,
  373. treeOnExpand,
  374. subjectTrees,
  375. getSubjectTree,
  376. modal,
  377. displayReader,
  378. onDisplayChange
  379. };
  380. },
  381. created() {
  382. if (history.state.params?.tempId) {
  383. console.log("created", history.state.params?.tempId);
  384. this.getTemp(history.state.params?.tempId);
  385. }
  386. },
  387. activated() {
  388. }
  389. });
  390. </script>
  391. <style lang="less" scoped>
  392. .ant-form-item {
  393. margin: 0 0 10px !important;
  394. }
  395. .ant-form-item-label label {
  396. width: 100% !important;
  397. background-color: #2dd36f;
  398. }
  399. .query-index {
  400. display: flex;
  401. flex-direction: row;
  402. height: 100%;
  403. background-color: white;
  404. }
  405. .query-index-tree {
  406. min-width: 260px;
  407. border-right: 2px solid #f2f2f2;
  408. margin-right: 5px;
  409. }
  410. .query-index-close {
  411. width: 15px;
  412. padding-top: 10px;
  413. padding-left: 10px;
  414. }
  415. .query-index-content {
  416. flex-grow: 1;
  417. display: flex;
  418. flex-direction: column;
  419. width: 80%;
  420. }
  421. .query-index-form {
  422. padding: 15px 10px 10px 15px;
  423. }
  424. .query-index-table {
  425. flex-grow: 1;
  426. }
  427. .query-index-tabs {
  428. margin-left: 10px;
  429. margin-right: 10px;
  430. height: 100%;
  431. }
  432. .tabs-view-content {
  433. padding: 0px;
  434. }
  435. .query-index-tree-item {
  436. white-space: nowrap; /*强制span不换行*/
  437. display: inline-block; /*将span当做块级元素对待*/
  438. text-overflow: ellipsis; /*超出部分以点号代替*/
  439. }
  440. .query-index-tree-search {
  441. padding: 5px;
  442. border-bottom: 2px solid #f2f2f2;
  443. display: flex;
  444. align-items: center;
  445. }
  446. .query-index-tree-box {
  447. padding: 5px;
  448. padding-top: 10px;
  449. overflow: auto;
  450. }
  451. .query-index-row {
  452. }
  453. </style>