addAnalysisSheet.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564
  1. <template>
  2. <div class="addSheet-wrap">
  3. <createTargetForm
  4. v-if="$route.path==='/createTaregtBySheet'"
  5. ref="createTargetRef"
  6. @save="handleCreateTarget"
  7. />
  8. <div class="main">
  9. <div class="left-section">
  10. <el-tabs
  11. v-model="selectIndex"
  12. type="card"
  13. >
  14. <el-tab-pane
  15. :key="item.name"
  16. v-for="(item,index) in uploadSheetsList"
  17. :label="item.name"
  18. :name="String(index)"
  19. />
  20. </el-tabs>
  21. <div class="sheet-wrapper">
  22. <Sheet ref="sheetRef" :option="sheetConfig" @updated="hasChange=true" v-if="sheetConfig.data" :limit="{disabled:false}"/>
  23. <dataLoading :loading="isLoading"/>
  24. </div>
  25. </div>
  26. <!-- 指标列表 -->
  27. <rightSection
  28. ref="edbWrapRef"
  29. v-if="$route.path==='/createTaregtBySheet'"
  30. :list="edbList"
  31. :sheetDetailInfo="this.sheetDetailInfo"
  32. :isEdbReFreshLoading="isEdbReFreshLoading"
  33. @refreshEdb="refreshSheet"
  34. @choose="chooseEdbHandle"
  35. />
  36. </div>
  37. <!-- 上传文件 -->
  38. <bottomSection
  39. ref="bottomSecRef"
  40. v-if="$route.path==='/addAnalysisSheet'"
  41. :sheetList="sheetConfig.data||[]"
  42. :classifyArr="classifyArr"
  43. @save="handleAddSheet"
  44. />
  45. </div>
  46. </template>
  47. <script>
  48. import * as sheetInterface from '@/api/modules/sheetApi.js';
  49. import Sheet from '../components/SheetExcel.vue';
  50. import { getSheetImage } from '../common/option';
  51. import bottomSection from './components/bottomSection.vue'
  52. import rightSection from './components/rightSection.vue';
  53. import createTargetForm from './components/createTargetForm.vue';
  54. export default {
  55. components: { Sheet,bottomSection,rightSection,createTargetForm },
  56. computed: {
  57. files() {
  58. return this.$store.state.sheet.files;
  59. },
  60. sheetConfig() {
  61. return this.$route.path==='/createTaregtBySheet'
  62. ? {
  63. showsheetbar: true,
  64. // allowCopy:false,
  65. // allowEdit:false,
  66. // allowUpdate:false,
  67. // enableAddRow:false,
  68. data: null,
  69. hook: {
  70. //选区时
  71. rangeSelect: (sheet,range) => {
  72. if(this.$refs.createTargetRef && this.$refs.createTargetRef.selectArea && !this.$refs.createTargetRef.isLockUpdate) this.getRangeCell()
  73. },
  74. }
  75. }
  76. : {
  77. showsheetbar: true,
  78. data: null
  79. }
  80. },
  81. },
  82. data() {
  83. return {
  84. isLoading: false,
  85. uploadSheetsList: [],
  86. pageSize: 2000,
  87. currentPage: 0,
  88. maxPage:0,
  89. selectIndex: '0',
  90. classifyArr: [],
  91. sheetDetailInfo: {},
  92. sheetDataPage: 2,
  93. sheetAllcellData:[],//全部单元格数据 分页push
  94. dataToalPage: 0,
  95. edbList: [],//生成的指标列表
  96. // 内容是否更新
  97. hasChange:false,
  98. isEdbReFreshLoading:false
  99. }
  100. },
  101. methods: {
  102. async saveApi(){
  103. luckysheet.exitEditMode();
  104. let data = luckysheet.getAllSheets();
  105. this.loading = this.$loading({
  106. target: ".dataSheet-container",
  107. lock: true,
  108. text: this.$t('MsgPrompt.saveing_msg') + "...",
  109. spinner: "el-icon-loading",
  110. background: "rgba(255, 255, 255, 0.6)",
  111. });
  112. let img = getSheetImage(data[0]);
  113. const form = new FormData();
  114. form.append("Image", img);
  115. form.append("closableErrMsg123", true);
  116. const { Data } = await sheetInterface.uploadImg(form);
  117. data.luckysheet_select_save = [];
  118. const { ExcelInfoId, ExcelName, ExcelClassifyId } = this.sheetDetailInfo;
  119. const res = await sheetInterface.sheetAnalysisInterface.sheetEdit({
  120. ExcelInfoId,
  121. ExcelName,
  122. ExcelClassifyId,
  123. ExcelImage: Data.ResourceUrl,
  124. Content: JSON.stringify(data),
  125. closableErrMsg123:true
  126. });
  127. this.loading.close();
  128. if (res.Ret !== 200) return false;
  129. this.hasChange=false
  130. this.shouldClosedHintshow(this.$t('MsgPrompt.saved_msg'))
  131. return true
  132. },
  133. /* 刷新表格 */
  134. refreshSheet: _.debounce(function() {
  135. if(this.isEdbReFreshLoading) return
  136. //退出编辑模式,让文本框失焦
  137. luckysheet.exitEditMode();
  138. // 保存逻辑延后 让hasChange取得正确的值
  139. setTimeout(async()=>{
  140. this.isEdbReFreshLoading = true;
  141. let res={}
  142. // 内容有改变 刷新前需要先保存
  143. if(this.hasChange){
  144. let saveSuccess = await this.saveApi()
  145. if(!saveSuccess){
  146. // 没保存成功
  147. this.isEdbReFreshLoading = false;
  148. return
  149. }
  150. res = await sheetInterface.sheetAnalysisInterface.sheetRefresh({ExcelInfoId: this.sheetDetailInfo.ExcelInfoId,closableErrMsg123:true})
  151. }else{
  152. res = await sheetInterface.sheetAnalysisInterface.sheetRefresh({ExcelInfoId: this.sheetDetailInfo.ExcelInfoId,closableErrMsg123:true})
  153. }
  154. this.isEdbReFreshLoading = false;
  155. if(res.Ret !== 200) return
  156. this.shouldClosedHintshow(res.Msg)
  157. })
  158. },300),
  159. shouldClosedHintshow(msg){
  160. let messageHint=this.$message.success({
  161. message:msg,
  162. duration:0,
  163. showClose:true
  164. })
  165. this.$store.commit('PUSH_CLOSABLE_HINT',messageHint)
  166. },
  167. backHandle(scence=null) {
  168. if(scence === 'into-detail') {
  169. const { ExcelInfoId, UniqueCode } = this.sheetDetailInfo;
  170. this.$router.replace({
  171. path: '/sheetAnalysisList',
  172. query: {
  173. code: UniqueCode,
  174. id: ExcelInfoId
  175. }
  176. })
  177. }else {
  178. this.$router.go(-1);
  179. }
  180. },
  181. /* 切换表格 */
  182. handleSwitchSheet() {
  183. this.sheetConfig.data = null;
  184. this.handelTranslateData();
  185. },
  186. /* 获取分类 */
  187. getClassify() {
  188. sheetInterface.sheetAnalysisInterface.getSheetTreeList({IsShare:false}).then((res) => {
  189. if(res.Ret !==200) return
  190. this.classifyArr = this.formatTreeData(_.cloneDeep(res.Data.AllNodes || []))
  191. })
  192. },
  193. formatTreeData(tree){
  194. function dfs(node){
  195. if (Array.isArray(node.Children)) {
  196. node.Children = node.Children.filter(dfs)
  197. if(node.Children.length===0) delete node.Children
  198. }
  199. if(node.ExcelInfoId) {
  200. return null
  201. }
  202. return node
  203. }
  204. return tree.filter(dfs)
  205. },
  206. /* 分割数据 */
  207. splitSheetData(sheets) {
  208. console.log(sheets)
  209. this.sheetConfig.data = sheets.map(_ => ({
  210. index: _.index, //工作表索引
  211. order: Number(_.order), //工作表的下标
  212. name: _.name,
  213. calcChain: _.calcChain,
  214. config: _.config,
  215. celldata: _.celldata,
  216. }));
  217. this.isLoading = false;
  218. },
  219. handelTranslateData() {
  220. this.isLoading = true;
  221. LuckyExcel.transformExcelToLucky(this.uploadSheetsList[Number(this.selectIndex)], (exportJson, luckysheetfile) =>{
  222. if(exportJson.sheets==null || exportJson.sheets.length==0){
  223. this.$message.warning(this.$t('OnlineExcelPage.parsing_file_error_msg') )
  224. return;
  225. }
  226. this.splitSheetData(exportJson.sheets);
  227. });
  228. },
  229. /* 移除表格 */
  230. handleRemoveSheet(index) {
  231. if(this.uploadSheetsList.length === 1) {
  232. this.backHandle()
  233. return
  234. }
  235. this.uploadSheetsList.splice(Number(index),1)
  236. if(this.selectIndex === index) {
  237. this.selectIndex = '0';
  238. this.handleSwitchSheet()
  239. }
  240. },
  241. /* 保存表格 */
  242. handleAddSheet: _.debounce(async function() {
  243. luckysheet.exitEditMode()
  244. let data = luckysheet.getAllSheets().filter(_ => this.$refs.bottomSecRef.sheetChecked.includes(_.name));
  245. console.log(data)
  246. this.loading = this.$loading({
  247. target:'.addSheet-wrap',
  248. lock: true,
  249. text: this.$t('OnlineExcelPage.saving_loading_text') ,
  250. spinner: 'el-icon-loading',
  251. background: 'rgba(255, 255, 255, 0.6)'
  252. });
  253. let img = getSheetImage(data[0]);
  254. const form = new FormData();
  255. form.append('Image', img);
  256. const { Data } = await sheetInterface.uploadImg(form)
  257. data.luckysheet_select_save = [];
  258. const res = await sheetInterface.sheetAnalysisInterface.excelSheetAdd({
  259. ExcelName: this.uploadSheetsList[0].name,
  260. ExcelClassifyId: this.$refs.bottomSecRef.select_classify,
  261. ExcelImage: Data.ResourceUrl,
  262. Content: JSON.stringify(data)
  263. })
  264. this.loading.close()
  265. if(res.Ret !== 200) return
  266. this.$message.success(res.Msg);
  267. this.$router.replace({
  268. path: '/sheetAnalysisList',
  269. })
  270. },300),
  271. /* 获取表格详情 */
  272. getDetailHandle() {
  273. this.isLoading = true;
  274. sheetInterface.sheetAnalysisInterface.getExcelDetail({
  275. UniqueCode: this.$route.query.code,
  276. }).then((res) => {
  277. if (res.Ret !== 200) return;
  278. this.sheetDetailInfo = res.Data.ExcelInfo;
  279. this.dataToalPage = Math.max(...res.Data.SheetList.map(_ => _.PageNum));
  280. this.sheetAllcellData = res.Data.SheetList.map(_ => _.Data ? JSON.parse(_.Data.Data): []);
  281. this.getCellData(res.Data.SheetList)
  282. });
  283. },
  284. //分页获取表格数据
  285. async getCellData(sheets) {
  286. let res = await sheetInterface.sheetAnalysisInterface.getExcelDataByPage({
  287. UniqueCode: this.$route.query.code,
  288. Page: this.sheetDataPage
  289. })
  290. if(res.Ret !== 200) return
  291. for(let i = 0;i<this.sheetAllcellData.length;i++) {
  292. if(res.Data[i].Data) {
  293. this.sheetAllcellData[i] = [...this.sheetAllcellData[i],...JSON.parse(res.Data[i].Data.Data)]
  294. }
  295. continue
  296. }
  297. //数据继续加载或渲染表格
  298. if(this.sheetDataPage < this.dataToalPage) {
  299. this.sheetDataPage++;
  300. this.getCellData(sheets)
  301. }else {
  302. this.sheetConfig.data = sheets.map((_,index) => ({
  303. index: _.Index, //工作表id
  304. order: _.Sort, //工作表的下标
  305. name: _.SheetName,
  306. calcChain: JSON.parse(_.CalcChain),
  307. config: JSON.parse(_.Config),
  308. celldata: this.sheetAllcellData[index],
  309. }))
  310. this.isLoading = false;
  311. //this.getTargetList()
  312. }
  313. },
  314. /* 获取选取对应单元格数组和拼接选取的公式
  315. Sheet1!$A$1:$A$25
  316. Sheet1!$E:$E
  317. */
  318. getRangeCell: _.debounce(function() {
  319. let sheet = luckysheet.getSheet();
  320. let rangeArr = luckysheet.getRangeAxis();
  321. if(rangeArr.length > 1) return this.$message.warning(this.$t('OnlineExcelPage.select_one_region_msg') );
  322. //检查选取是否满足同行/同列
  323. if(!this.checkRangeVaild(rangeArr[0])) return this.$message.warning(this.$t('OnlineExcelPage.only_allowed_select_msg') );
  324. let rangeCells = luckysheet.getRangeValue().flat().map(_=>_?_.m:'');
  325. let format = `${sheet.name}!${this.formatStr(rangeArr[0])}`;
  326. console.log(format)
  327. this.$refs.createTargetRef.setFormula(format,rangeCells)
  328. },300),
  329. //检验同行同列
  330. checkRangeVaild(range) {
  331. let reg = /^([A-Z]+)(\d+)$/;
  332. let arr = range.split(':').map(_ => [_.match(reg)[1],_.match(reg)[2]]);
  333. if(arr.length ===1) return true;
  334. if(arr[0][0] === arr[1][0] || arr[0][1] === arr[1][1]) {
  335. return true
  336. }else {
  337. return false
  338. }
  339. },
  340. formatStr(inputRange) {
  341. // 将字母和数字前面都拼接"$"
  342. const parts = inputRange.split(':');
  343. if (parts.length === 2) {
  344. const start = parts[0].replace(/(^[A-Z]+)(\d+)$/, '$$$1$$$2');
  345. const end = parts[1].replace(/(^[A-Z]+)(\d+)$/, '$$$1$$$2');
  346. return start + ':' + end;
  347. }
  348. return inputRange;
  349. },
  350. /* 生成指标 */
  351. async handleCreateTarget() {
  352. console.log(this.$refs.createTargetRef.formData)
  353. this.loading = this.$loading({
  354. target:'.addSheet-wrap',
  355. lock: true,
  356. text: this.$t('OnlineExcelPage.saving_loading_text') ,
  357. spinner: 'el-icon-loading',
  358. background: 'rgba(255, 255, 255, 0.6)'
  359. });
  360. let data = luckysheet.getAllSheets();
  361. data.luckysheet_select_save = [];
  362. const { ExcelInfoId, ExcelName, ExcelClassifyId } = this.sheetDetailInfo;
  363. await sheetInterface.sheetAnalysisInterface.sheetEdit({
  364. ExcelInfoId,
  365. ExcelName,
  366. ExcelClassifyId,
  367. // ExcelImage: Data.ResourceUrl,
  368. Content: JSON.stringify(data)
  369. });
  370. const { edbInfoId,
  371. dateSeries,
  372. valueSeries,
  373. dateArr,
  374. valueArr,
  375. edbName,
  376. classify,
  377. frequency,
  378. unit } = this.$refs.createTargetRef.formData;
  379. let params = {
  380. EdbName: edbName,
  381. ExcelInfoId: ExcelInfoId,
  382. ClassifyId: classify,
  383. Frequency: frequency,
  384. Unit: unit,
  385. DateSequenceVal: dateArr,
  386. DataSequenceVal: valueArr,
  387. DateSequenceStr: dateSeries,
  388. DataSequenceStr: valueSeries
  389. }
  390. const res = edbInfoId
  391. ? await sheetInterface.sheetAnalysisInterface.edbEditBysheet({...params,EdbInfoId: edbInfoId})
  392. : await sheetInterface.sheetAnalysisInterface.edbAddBysheet(params)
  393. this.loading.close();
  394. if(res.Ret !== 200) return
  395. this.$message.success(res.Msg)
  396. if(!edbInfoId) this.$refs.createTargetRef.initData();
  397. //this.getTargetList()
  398. if(this.$refs.edbWrapRef){
  399. this.$refs.edbWrapRef.getTargetList('init')
  400. }
  401. },
  402. /* 获取生成指标列表 */
  403. async getTargetList() {
  404. const res = await sheetInterface.sheetAnalysisInterface.edbListBySheet({
  405. ExcelInfoId: this.sheetDetailInfo.ExcelInfoId
  406. })
  407. if(res.Ret !== 200) return
  408. this.edbList = res.Data || [];
  409. },
  410. /* 选择指标列表更新表单信息和区域选中 */
  411. chooseEdbHandle() {
  412. if(this.$refs.edbWrapRef.selectEdb.EdbInfoId) {
  413. this.$refs.createTargetRef.initData(this.$refs.edbWrapRef.selectEdb)
  414. } else {
  415. this.$refs.createTargetRef.initData()
  416. }
  417. }
  418. },
  419. mounted() {
  420. this.getClassify();
  421. //上传文件的解析渲染
  422. if(this.files) {
  423. this.uploadSheetsList = Object.values(this.files);
  424. this.handelTranslateData()
  425. this.$store.commit('sheet/SET_UPLOADFIlES',null)
  426. }
  427. //详情的渲染
  428. if(this.$route.query.code) this.getDetailHandle();
  429. }
  430. }
  431. </script>
  432. <style scoped lang="scss">
  433. *{ box-sizing: border-box; }
  434. .addSheet-wrap {
  435. min-height: calc(100vh - 120px);
  436. .wrap-top {
  437. display: flex;
  438. justify-content: space-between;
  439. align-items: center;
  440. margin-bottom: 20px;
  441. padding: 20px;
  442. background: #fff;
  443. border: 1px solid #ececec;
  444. border-radius: 4px;
  445. box-shadow: 0 3px 6px rgba(0, 0, 0, 0.05);
  446. display: flex;
  447. z-index: 1;
  448. .form-ul {
  449. flex: 1;
  450. display: flex;
  451. li {
  452. margin-right: 30px;
  453. }
  454. }
  455. }
  456. .main {
  457. display: flex;
  458. position: relative;
  459. min-height: 700px;
  460. .left-section {
  461. flex:1;
  462. .sheet-wrapper {
  463. position: relative;
  464. background: #fff;
  465. min-height: 700px;
  466. }
  467. }
  468. &.full-height {
  469. min-height: calc(100vh - 120px);
  470. }
  471. }
  472. }
  473. </style>
  474. <style lang="scss">
  475. .addSheet-wrap {
  476. .el-tabs__nav {
  477. background: #fff;
  478. }
  479. .el-tabs__header {
  480. margin-bottom: 0;
  481. // border-bottom: none;
  482. }
  483. }
  484. </style>