index.vue 77 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260
  1. <template>
  2. <div class="cqcy-content" style="margin: 0;height: calc(100% - 70px);">
  3. <breadcrumb-view :breadcrumbList="breadcrumbList" :show-index="false"></breadcrumb-view>
  4. <div v-if="btnType === ''" class="cy-nav-sx">
  5. <el-select v-model="searchValue"
  6. style="width: 180px;"
  7. placeholder="请选择报表类型"
  8. @change="changeReportTypeEvent">
  9. <el-option v-for="item in reportOptions"
  10. style="margin-left: 5px; width: 180px;"
  11. :key="item.value"
  12. :label="item.label"
  13. :value="item.value">
  14. </el-option>
  15. </el-select>
  16. <el-input placeholder="请输入报表名称"
  17. v-model="searchTxt"
  18. style="margin-left: 5px; width: 180px;"
  19. prefix-icon="el-icon-search">
  20. </el-input>
  21. <el-button style="margin-left: 5px;" @click="searchReportEvent">查询</el-button>
  22. </div>
  23. <el-button v-if="btnType === ''" type="primary" class="cy-nav-btn" icon="el-icon-circle-plus-outline"
  24. size="mini" @click="addReportEvent">新增
  25. </el-button>
  26. <!-- <el-button v-if="btnType === ''" type="success" class="cy-nav-btn" icon="el-icon-refresh"-->
  27. <!-- size="mini" @click="refreshReportEvent">刷新</el-button>-->
  28. <el-divider></el-divider>
  29. <div class="cy-main">
  30. <div class="cy-main-left" v-if="!showMainView">
  31. <div class="cy-list">
  32. <el-table v-if="reportDataList.length > 0"
  33. :data="reportDataList"
  34. border
  35. :stripe="true"
  36. :header-cell-style="{background: '#E8E8E8'}"
  37. @sort-change="sortChange"
  38. style="width: 100%;">
  39. <el-table-column
  40. align="center"
  41. sortable="custom"
  42. label="报表名称"
  43. prop="reportTableName">
  44. <template slot-scope="scope">
  45. <span style="color: #409EFF; cursor: pointer;"
  46. @click="handleReportNodeClick(scope.row, scope.row.userId != uid ? 'deny' : '')"
  47. :title="scope.row.reportTableName">{{ scope.row.reportTableName }}</span>
  48. </template>
  49. </el-table-column>
  50. <el-table-column
  51. align="center"
  52. label="报表状态"
  53. prop="isAutoReport"
  54. width="350">
  55. <template slot-scope="scope">
  56. <el-tag v-if="scope.row.userId != uid" type="success" style="margin-right: 5px;">被分享</el-tag>
  57. <el-tag v-if="uid == scope.row.userId && scope.row.userGroupList && scope.row.userGroupList.length > 0"
  58. type="warning" style="margin-right: 5px;">已分享
  59. </el-tag>
  60. <el-tag v-if="scope.row.isAutoReport == 0" style="margin-right: 5px;">手动报表</el-tag>
  61. <el-tag v-if="scope.row.isAutoReport == 1" style="margin-right: 5px;">自动报表</el-tag>
  62. <el-tag v-if="scope.row.isAutoReport == 3" style="margin-right: 5px;">事件驱动报表</el-tag>
  63. </template>
  64. </el-table-column>
  65. <!-- <el-table-column-->
  66. <!-- align="center"-->
  67. <!-- label="自动报表"-->
  68. <!-- prop="isAutoReport"-->
  69. <!-- width="150">-->
  70. <!-- <template slot-scope="scope">-->
  71. <!-- <el-switch v-if="scope.row.isAutoReport == '2'" :value="true" active-color="#13ce66"-->
  72. <!-- disabled></el-switch>-->
  73. <!-- <el-switch v-else :value="scope.row.isAutoReport == '1'" active-color="#13ce66"-->
  74. <!-- @change="switchChangeEvent($event, scope.row)"-->
  75. <!-- :disabled="uid != scope.row.userId"></el-switch>-->
  76. <!-- </template>-->
  77. <!-- </el-table-column>-->
  78. <el-table-column
  79. align="center"
  80. label="当前版本"
  81. sortable="custom"
  82. prop="version"
  83. width="120">
  84. </el-table-column>
  85. <el-table-column
  86. align="center"
  87. label="创建时间"
  88. sortable
  89. prop="createTime"
  90. width="200">
  91. </el-table-column>
  92. <el-table-column label="操作" align="center" width="380">
  93. <template slot-scope="scope">
  94. <el-button type="text"
  95. v-if="uid == scope.row.userId"
  96. size="small"
  97. icon="el-icon-edit"
  98. @click="editReportItem(scope.row)">修改名称
  99. </el-button>
  100. <el-button type="text"
  101. v-if="uid == scope.row.userId"
  102. size="small"
  103. icon="el-icon-setting"
  104. @click="setReportStatus(scope.row)">设置报表状态
  105. </el-button>
  106. <el-button type="text"
  107. v-if="uid == scope.row.userId"
  108. size="small"
  109. icon="el-icon-user"
  110. @click="setUserGroupEvent(scope.row)">授权
  111. </el-button>
  112. <el-button type="text"
  113. v-if="uid == scope.row.userId"
  114. size="small"
  115. icon="el-icon-document"
  116. @click="getUserGroupEvent(scope.row)">授权详情
  117. </el-button>
  118. <el-button type="text"
  119. v-if="uid == scope.row.userId"
  120. size="small"
  121. icon="el-icon-delete"
  122. style="color: red;"
  123. @click="removeReportItem(scope.row)">删除
  124. </el-button>
  125. </template>
  126. </el-table-column>
  127. </el-table>
  128. <el-empty v-else description="暂无数据"></el-empty>
  129. </div>
  130. <el-pagination
  131. background
  132. @size-change="handleSizeChange"
  133. @current-change="handleCurrentChange"
  134. :current-page="reportPage"
  135. :page-size="reportLimit"
  136. layout="sizes, prev, pager, next, total"
  137. :total="reportTotal">
  138. </el-pagination>
  139. </div>
  140. <div class="cy-main-right" :style="showMainView ? '' : 'display: none;'">
  141. <el-row v-if="btnType == 'add'" style="margin: 10px 20px;">
  142. <el-button type="primary" size="mini" icon="el-icon-document" @click="saveReportInfo">保存报表</el-button>
  143. <el-button type="danger" size="mini" icon="el-icon-circle-close" @click="cancelSaveReport">取消</el-button>
  144. </el-row>
  145. <el-row v-if="btnType == 'show'" style="margin: 10px 20px;">
  146. <el-button type="success" size="mini" icon="el-icon-document-checked" @click="updateReport">保存</el-button>
  147. <el-button type="primary" size="mini" icon="el-icon-download" @click="downloadReport">下载</el-button>
  148. <el-button type="warning" size="mini" icon="el-icon-printer" @click="printExcel">打印</el-button>
  149. <el-button type="info" size="mini" icon="el-icon-document" @click="historyReport">运行记录</el-button>
  150. <el-button type="danger" size="mini" icon="el-icon-circle-close" @click="cancelSaveReport">关闭</el-button>
  151. </el-row>
  152. <el-row v-if="btnType == 'showShared'" style="margin: 10px 20px;">
  153. <el-button type="primary" size="mini" icon="el-icon-download" @click="downloadReport">下载</el-button>
  154. <el-button type="warning" size="mini" icon="el-icon-printer" @click="printExcel">打印</el-button>
  155. <el-button type="info" size="mini" icon="el-icon-document" @click="historyReport">运行记录</el-button>
  156. <el-button type="danger" size="mini" icon="el-icon-circle-close" @click="cancelSaveReport">关闭</el-button>
  157. </el-row>
  158. <el-row v-if="btnType == 'showChild'" style="margin: 10px 20px;">
  159. <el-button type="primary" size="mini" icon="el-icon-download" @click="downloadReport">下载</el-button>
  160. <el-button type="warning" size="mini" icon="el-icon-printer" @click="printExcel">打印</el-button>
  161. <el-button type="danger" size="mini" icon="el-icon-circle-close" @click="cancelSaveReport2">关闭</el-button>
  162. </el-row>
  163. <div id="luckysheet"
  164. style="margin:0px;padding:0px;position:relative;height:calc(100% - 50px);width:100%;left: 20px;top: 0px;bottom:0px;">
  165. </div>
  166. </div>
  167. </div>
  168. <!-- 新增报表 -->
  169. <el-dialog
  170. title="新增报表"
  171. width="50%"
  172. top="10vh"
  173. center
  174. v-dialog-drag
  175. v-if="dialogReportTemplateVisible"
  176. :before-close="dialogClose"
  177. :visible.sync="dialogReportTemplateVisible"
  178. :close-on-click-modal="false"
  179. :append-to-body="true">
  180. <el-form ref="reportForm" :model="reportForm" :rules="reportRules" label-width="80px">
  181. <el-form-item label="报表模板" prop="reportTemplate">
  182. <el-select v-model="reportForm.reportTemplate" filterable placeholder="请选择报表模板" style="width: 100%;">
  183. <el-option
  184. v-for="item in reportTemplateList"
  185. :key="item.id"
  186. :label="item.templateName"
  187. :value="item.id">
  188. </el-option>
  189. </el-select>
  190. </el-form-item>
  191. <el-form-item label="取值方式" prop="reportValueFormat">
  192. <el-radio v-model="reportForm.reportValueFormat" label="0">时段数据</el-radio>
  193. </el-form-item>
  194. <el-form-item label='取值模式' prop="valueCondition">
  195. <el-select v-model="reportForm.valueCondition" placeholder="请选择报表取值模式" style="width: 100%;">
  196. <el-option
  197. v-for="dict in valueConditionList"
  198. :key="dict.value"
  199. :label="dict.key"
  200. :value="dict.value"
  201. ></el-option>
  202. </el-select>
  203. </el-form-item>
  204. <el-form-item label="报表类型" prop="isAutoReport">
  205. <el-select v-model="reportForm.isAutoReport" filterable placeholder="请选择报表类型" style="width: 100%;">
  206. <el-option
  207. v-for="item in reportOptions_"
  208. :key="item.value"
  209. :label="item.label"
  210. :value="item.value">
  211. </el-option>
  212. </el-select>
  213. </el-form-item>
  214. <el-form-item label="数据时间" prop="reportDate">
  215. <el-date-picker
  216. v-model="reportForm.reportDate" :editable="false" :clearable="false"
  217. style="width: 100%;"
  218. type="datetimerange"
  219. :picker-options="{
  220. format: 'yyyy-MM-dd HH:mm:ss'
  221. }"
  222. value-format="yyyy-MM-dd HH:mm:ss"
  223. range-separator="至"
  224. start-placeholder="开始日期"
  225. end-placeholder="结束日期">
  226. </el-date-picker>
  227. </el-form-item>
  228. <el-form-item style="text-align: center;">
  229. <el-button type="primary" @click="chooseReportEvent" style="margin-top: 20px;">确定</el-button>
  230. <el-button @click="dialogClose" style="margin-top: 20px;">取消</el-button>
  231. </el-form-item>
  232. </el-form>
  233. </el-dialog>
  234. <!-- 用户组选择 -->
  235. <el-dialog
  236. title="选择用户组"
  237. width="840px"
  238. top="10vh"
  239. center
  240. v-dialog-drag
  241. v-if="dialogUserGroupVisible"
  242. :before-close="dialogClose"
  243. :visible.sync="dialogUserGroupVisible"
  244. :close-on-click-modal="false"
  245. :append-to-body="true">
  246. <!-- <el-form label-width="80px">-->
  247. <!-- <el-form-item label="用户组">-->
  248. <!-- <el-select v-model="userGroupInfo" filterable clearable multiple placeholder="请选择用户组" style="width: 100%;">-->
  249. <!-- <el-option-->
  250. <!-- v-for="item in userGroupList"-->
  251. <!-- :key="item.id"-->
  252. <!-- :label="item.userGroupName"-->
  253. <!-- :value="item.id">-->
  254. <!-- </el-option>-->
  255. <!-- </el-select>-->
  256. <!-- </el-form-item>-->
  257. <!-- </el-form>-->
  258. <div class="ug-div">
  259. <el-transfer
  260. v-model="userGroupInfo"
  261. :titles="['用户组列表', '已选择用户组']"
  262. :data="userGroupList"
  263. :props="{
  264. key: 'id',
  265. label: 'userGroupName'
  266. }">
  267. </el-transfer>
  268. </div>
  269. <span slot='footer'>
  270. <el-button type="primary" @click="chooseUserGroupEvent" style="margin-top: 20px;">确定</el-button>
  271. <el-button @click="dialogClose" style="margin-top: 20px;">取消</el-button>
  272. </span>
  273. </el-dialog>
  274. <!-- 自动报表CRON定时表达式 -->
  275. <el-dialog
  276. title="配置定时任务"
  277. width="50%"
  278. top="10vh"
  279. center
  280. v-dialog-drag
  281. v-if="dialogAutoReportVisible"
  282. :before-close="dialogClose"
  283. :visible.sync="dialogAutoReportVisible"
  284. :close-on-click-modal="false"
  285. :append-to-body="true">
  286. <el-form label-width="80px">
  287. <el-radio-group v-model="radioByCron">
  288. <el-form-item label="秒">
  289. <el-radio :label="1">
  290. <span style="margin-right: 10px;">每</span>
  291. <el-input-number size="mini" v-model="radioByCronValS" :min="1" :max="59"></el-input-number>
  292. <span style="margin-left: 10px;">秒执行一次</span>
  293. </el-radio>
  294. </el-form-item>
  295. <el-form-item label="分钟">
  296. <el-radio :label="2">
  297. <span style="margin-right: 10px;">每</span>
  298. <el-input-number size="mini" v-model="radioByCronValM" :min="1" :max="59"></el-input-number>
  299. <span style="margin-left: 10px;">分钟执行一次</span>
  300. </el-radio>
  301. </el-form-item>
  302. <el-form-item label="小时">
  303. <el-radio :label="3">
  304. <span style="margin-right: 10px;">每</span>
  305. <el-input-number size="mini" v-model="radioByCronValH" :min="1" :max="2"></el-input-number>
  306. <span style="margin-left: 10px;">小时执行一次</span>
  307. </el-radio>
  308. </el-form-item>
  309. <el-form-item label="指定时间">
  310. <el-radio :label="4">
  311. <span style="margin-right: 10px;">在每天的</span>
  312. <el-time-picker v-model="radioByCronValD"
  313. size="mini"
  314. placeholder="请选择时间"
  315. :clearable="false"
  316. :editable="false"
  317. value-format="HH:mm:ss"
  318. :picker-options="{
  319. format: 'HH:mm:ss'
  320. }">
  321. </el-time-picker>
  322. <span style="margin-left: 10px;">执行一次</span>
  323. </el-radio>
  324. </el-form-item>
  325. <el-form-item label="">
  326. <el-radio :label="5">
  327. <span style="margin-right: 10px;">在每月</span>
  328. <el-input-number size="mini" v-model="radioByCronValMo" :min="1" :max="31"></el-input-number>
  329. <span style="margin-right: 10px; margin-left: 10px;">号的</span>
  330. <el-time-picker v-model="radioByCronValMoD"
  331. size="mini"
  332. placeholder="请选择时间"
  333. :clearable="false"
  334. :editable="false"
  335. value-format="HH:mm:ss"
  336. :picker-options="{
  337. format: 'HH:mm:ss'
  338. }">
  339. </el-time-picker>
  340. <span style="margin-left: 10px;">执行一次</span>
  341. </el-radio>
  342. </el-form-item>
  343. </el-radio-group>
  344. <!-- <el-form-item label="表达式">-->
  345. <!-- <el-input type="text" placeholder="请输入定时任务表达式" v-model="cronVal" maxlength="50"></el-input>-->
  346. <!-- </el-form-item>-->
  347. <!-- <div>-->
  348. <!-- <label>常用定时任务表达式例子</label>-->
  349. <!-- <ul>-->
  350. <!-- <li v-for="(item, i) in cronList" style="margin-bottom: 5px;">-->
  351. <!-- <span class="cron-txt" @click="cronNodeEvent(item)">{{ item.value }}</span>-->
  352. <!-- <span class="cron-txt-desc">{{ item.label }}</span>-->
  353. <!-- </li>-->
  354. <!-- </ul>-->
  355. <!-- </div>-->
  356. </el-form>
  357. <span slot='footer'>
  358. <el-button type="primary" @click="chooseCronEvent">确定</el-button>
  359. <el-button @click="dialogClose">取消</el-button>
  360. </span>
  361. </el-dialog>
  362. <!-- 报表类型 -->
  363. <el-dialog
  364. title="报表类型选择"
  365. width="50%"
  366. top="10vh"
  367. center
  368. v-dialog-drag
  369. v-if="dialogReportTypeVisible"
  370. :before-close="dialogClose"
  371. :visible.sync="dialogReportTypeVisible"
  372. :close-on-click-modal="false"
  373. :append-to-body="true">
  374. <div style="text-align: center;">
  375. <el-radio v-model="reportType" label="0">手动报表</el-radio>
  376. <el-radio v-model="reportType" label="1">自动报表</el-radio>
  377. <el-radio v-model="reportType" label="3">事件驱动报表</el-radio>
  378. </div>
  379. <span slot='footer'>
  380. <el-button type="primary" @click="chooseReportTypeEvent">确定</el-button>
  381. <el-button @click="dialogClose">取消</el-button>
  382. </span>
  383. </el-dialog>
  384. <!-- 报表下载类型选择 -->
  385. <el-dialog
  386. title="选择下载类型"
  387. width="500px"
  388. center
  389. v-dialog-drag
  390. v-if="dialogDownloadReportTypeVisible"
  391. :before-close="dialogClose"
  392. :visible.sync="dialogDownloadReportTypeVisible"
  393. :close-on-click-modal="false"
  394. :append-to-body="true">
  395. <div style="text-align: center;">
  396. <el-radio v-model="downloadType" label="1">Excel</el-radio>
  397. <!-- <el-radio v-model="downloadType" label="2" disabled>PDF</el-radio>-->
  398. </div>
  399. <div style="text-align: center; margin-top: 40px;">
  400. <el-button type="primary" @click="downloadReportEvent">确定</el-button>
  401. </div>
  402. </el-dialog>
  403. <!-- 历史报表查看 -->
  404. <el-dialog
  405. title="运行报表记录"
  406. width="80%"
  407. top="10vh"
  408. center
  409. v-dialog-drag-and-zoom
  410. v-if="dialogHistoryReportVisible"
  411. :before-close="dialogClose"
  412. :visible.sync="dialogHistoryReportVisible"
  413. :close-on-click-modal="false"
  414. :append-to-body="true">
  415. <div style="height: 60vh;">
  416. <el-table
  417. :data="reportHistoryData" border :stripe="true"
  418. :header-cell-style="{background: '#E8E8E8'}"
  419. @sort-change="sortChange1"
  420. style="width: 100%; height: calc(100% - 50px); overflow: auto;">
  421. <el-table-column
  422. align="center"
  423. sortable="custom"
  424. label="报表名称"
  425. prop="reportTableName">
  426. <template slot-scope="scope">
  427. <span style="color: #409EFF; cursor: pointer;"
  428. @click="handleReportNodeClick(scope.row, 'history')"
  429. :title="scope.row.reportTableName">{{ scope.row.reportTableName }}</span>
  430. </template>
  431. </el-table-column>
  432. <!-- <el-table-column-->
  433. <!-- align="center"-->
  434. <!-- label="报表状态"-->
  435. <!-- prop="isAutoReport"-->
  436. <!-- width="180">-->
  437. <!-- <template slot-scope="scope">-->
  438. <!-- <el-tag v-if="scope.row.userId != uid" type="success" style="margin-right: 5px;">被分享</el-tag>-->
  439. <!-- <el-tag v-if="uid == scope.row.userId && scope.row.userGroupList && scope.row.userGroupList.length > 0"-->
  440. <!-- type="warning" style="margin-right: 5px;">已分享</el-tag>-->
  441. <!-- </template>-->
  442. <!-- </el-table-column>-->
  443. <el-table-column
  444. align="center"
  445. label="当前版本"
  446. sortable="custom"
  447. prop="version"
  448. width="120">
  449. </el-table-column>
  450. <el-table-column
  451. align="center"
  452. label="运行时间"
  453. sortable
  454. prop="createTime"
  455. width="200">
  456. </el-table-column>
  457. <el-table-column label="操作" align="center" width="300">
  458. <template slot-scope="scope">
  459. <el-button type="text"
  460. v-if="uid == scope.row.userId"
  461. size="small"
  462. icon="el-icon-delete"
  463. style="color: red;"
  464. @click="removeReportItem(scope.row, 'record')">删除
  465. </el-button>
  466. </template>
  467. </el-table-column>
  468. </el-table>
  469. <el-pagination
  470. style="margin-top: 20px;"
  471. background
  472. layout="sizes, prev, pager, next, total"
  473. :current-page="reportHistoryPage"
  474. :page-size="reportHistoryLimit"
  475. @size-change="sizeHistoryChangeEvent"
  476. @current-change="currentHistoryChangeEvent"
  477. :total="reportHistoryTotal">
  478. </el-pagination>
  479. </div>
  480. </el-dialog>
  481. <!-- 用户组用户人员查看 -->
  482. <el-dialog
  483. title="授权详情"
  484. width="600px"
  485. top="10vh"
  486. center
  487. v-dialog-drag
  488. v-if="dialogGroupUserVisible"
  489. :before-close="dialogGroupUserClose"
  490. :visible.sync="dialogGroupUserVisible"
  491. :close-on-click-modal="false"
  492. :append-to-body="true">
  493. <div style="height: 60vh;">
  494. <el-table
  495. :data="groupUserData" border :stripe="true"
  496. :header-cell-style="{background: '#E8E8E8'}"
  497. style="width: 100%; height: calc(100% - 50px); overflow: auto;">
  498. <el-table-column
  499. align="center"
  500. label="用户组名称"
  501. prop="userGroupName">
  502. </el-table-column>
  503. <el-table-column
  504. align="center"
  505. label="姓名"
  506. prop="userName">
  507. </el-table-column>
  508. </el-table>
  509. </div>
  510. </el-dialog>
  511. <div id="print-area"
  512. style="display: none;position: absolute;z-index: 0;top: 0;width: 100%;height: 100vh;overflow: hidden;">
  513. <div id="print-html" ref="printPayFeeNew"></div>
  514. </div>
  515. </div>
  516. </template>
  517. <script>
  518. import BreadcrumbView from '@/components/BreadcrumbView'
  519. import {
  520. customCompare,
  521. getLuckysheetConfig,
  522. getNowFormatDate,
  523. showAlertWin, showConfirmWin,
  524. showLoading, showPromptWin
  525. } from '@/utils/cqcy'
  526. import {
  527. delReportTableById,
  528. getAllDataModel,
  529. getAllOkReportTable,
  530. getAllTableTemplate,
  531. getAutoChReportTable,
  532. getChartData,
  533. getDataModelById,
  534. getReportTableById,
  535. getTableData,
  536. getTableTemplateById,
  537. getUserByGroupId,
  538. saveReport,
  539. tableAssignUserById,
  540. tableExchangeTypeById,
  541. updateReportTable,
  542. updateTableNameById
  543. } from '@/api/datasource'
  544. import Print from 'print-js'
  545. import {getUsername} from '@/utils/auth'
  546. import {exportExcel} from '@/utils/export'
  547. import {getAllUserGroup} from "@/api/user";
  548. import {mapGetters} from "vuex";
  549. import {insertLuckysheetEChart} from "@/utils/luckysheettool";
  550. export default {
  551. name: "index",
  552. components: {
  553. BreadcrumbView
  554. },
  555. computed: {
  556. ...mapGetters([
  557. 'name',
  558. 'uid'
  559. ])
  560. },
  561. data() {
  562. return {
  563. breadcrumbList: ['运行配置'],
  564. groupProps: {
  565. isLeaf: 'leaf'
  566. },
  567. showMainView: false,
  568. chooseMyReport: null,
  569. dialogReportTemplateVisible: false,
  570. dialogDownloadReportTypeVisible: false,
  571. dialogAutoReportVisible: false,
  572. dialogReportTypeVisible: false,
  573. dialogUserGroupVisible: false,
  574. dialogHistoryReportVisible: false,
  575. dialogGroupUserVisible: false,
  576. reportType: '0',
  577. downloadType: '1',
  578. btnType: '',
  579. hasUserGroup: false,
  580. userGroupInfo: null,
  581. userGroupList: [],
  582. radioByCron: null,
  583. radioByCronValS: '',
  584. radioByCronValM: '',
  585. radioByCronValH: '',
  586. radioByCronValD: null,
  587. radioByCronValMo: '',
  588. radioByCronValMoD: null,
  589. cronVal: '',
  590. cronList: [],
  591. reportId: null,
  592. reportTemplateList: [],
  593. dataModelList: [],
  594. chooseReportTemplate: null,
  595. chooseReportTemplateId: null,
  596. chooseIsAutoReport: null,
  597. delFlag: 0,
  598. reportForm: {
  599. reportTemplate: null,
  600. reportValueFormat: '0', // 时间取值格式0时,1日,2月
  601. isAutoReport: 0,
  602. valueCondition: null, // 报表取值条件:0平均值 1最大值 2最小值 3瞬时值
  603. reportDate: [getNowFormatDate('yyyy-MM-dd') + ' 09:00:00',
  604. getNowFormatDate('yyyy-MM-dd') + ' 18:00:00']
  605. },
  606. searchValue: null,
  607. searchTxt: '',
  608. valueConditionList: [{
  609. 'key': '平均值',
  610. 'value': '0'
  611. }, {
  612. 'key': '最大值',
  613. 'value': '1'
  614. }, {
  615. 'key': '最小值',
  616. 'value': '2'
  617. }, {
  618. 'key': '瞬时值',
  619. 'value': '3'
  620. }],
  621. reportOptions: [{
  622. label: '所有报表',
  623. value: -1
  624. }, {
  625. label: '手动报表',
  626. value: 0
  627. }, {
  628. label: '自动报表',
  629. value: 1
  630. }, {
  631. label: '事件驱动报表',
  632. value: 3
  633. }],
  634. reportOptions_: [{
  635. label: '手动报表',
  636. value: 0
  637. }, {
  638. label: '事件驱动报表',
  639. value: 3
  640. }],
  641. groupUserData: [],
  642. reportHistoryData: [],
  643. reportHistoryTotal: 0,
  644. reportHistoryPage: 1,
  645. reportHistoryLimit: 10,
  646. reportTotal: 0,
  647. reportPage: 1,
  648. reportLimit: 10,
  649. reportDataList: [],
  650. reportRules: {
  651. reportTemplate: [
  652. {required: true, message: '请选择报表模板', trigger: 'change'}
  653. ],
  654. reportValueFormat: [
  655. {required: true, message: '请选择取值方式', trigger: 'change'}
  656. ],
  657. valueCondition: [
  658. { required: true, message: '请选择报表取值模式', trigger: 'blur' }
  659. ],
  660. isAutoReport: [
  661. {required: true, message: '请选择报表类型', trigger: 'change'}
  662. ],
  663. reportDate: [
  664. {required: true, message: '请选择数据时间'}
  665. ]
  666. },
  667. luckysheetOption: {
  668. container: 'luckysheet', // 设定 DOM 容器的 id
  669. title: '报表模板', // 设定表格名称
  670. lang: 'zh', // 设定表格语言
  671. showinfobar: false, // 是否显示顶部信息栏
  672. showtoolbar: false, // 是否显示工具栏
  673. showtoolbarConfig: {
  674. paintFormat: true, //格式刷
  675. moreFormats: true, // 单元格格式
  676. font: true, // 字体
  677. fontSize: true, // 字号大小
  678. bold: true, // 粗体 (Ctrl+B)
  679. italic: true, // 斜体 (Ctrl+I)
  680. strikethrough: true, // 删除线 (Alt+Shift+5)
  681. underline: true, // 下划线 (Alt+Shift+6)
  682. textColor: true, // 文本颜色
  683. fillColor: true, // 单元格颜色
  684. border: true, // 边框
  685. mergeCell: true, // 合并单元格
  686. horizontalAlignMode: true, // 水平对齐方式
  687. verticalAlignMode: true, // 垂直对齐方式
  688. function: true, // 公式
  689. // image: true
  690. // chart: true
  691. },
  692. showsheetbar: false, // 是否显示底部 sheet 页按钮
  693. sheetFormulaBar: false, // 是否显示公式
  694. row: 100, // 是否显示底部 sheet 页按钮
  695. data: [{
  696. "name": "统计报表", //工作表名称
  697. }],
  698. cellRightClickConfig: { // 自定义配置单元格右击菜单
  699. copy: true, // 复制
  700. copyAs: false, // 复制为
  701. paste: true, // 粘贴
  702. insertRow: true, // 插入行
  703. insertColumn: true, // 插入列
  704. deleteRow: true, // 删除选中行
  705. deleteColumn: true, // 删除选中列
  706. deleteCell: false, // 删除单元格
  707. hideRow: false, // 隐藏选中行和显示选中行
  708. hideColumn: false, // 隐藏选中列和显示选中列
  709. rowHeight: true, // 行高
  710. columnWidth: true, // 列宽
  711. clear: false, // 清除内容
  712. matrix: false, // 矩阵操作选区
  713. sort: false, // 排序选区
  714. filter: false, // 筛选选区
  715. chart: true, // 图表生成
  716. image: false, // 插入图片
  717. link: false, // 插入链接
  718. data: false, // 数据验证
  719. cellFormat: false // 设置单元格格式
  720. },
  721. plugins: ['chart']
  722. }
  723. }
  724. },
  725. watch: {},
  726. beforeDestroy() {
  727. this.chooseMyReport = null
  728. },
  729. mounted() {
  730. let _this = this
  731. document.onkeyup = function (event) {
  732. let e = event || window.event || arguments.callee.caller.arguments[0]
  733. if (!e) return
  734. const {key, keyCode} = e
  735. if (keyCode === 46 || keyCode === 8) {
  736. _this.forceRefreshLuckysheet()
  737. }
  738. }
  739. },
  740. created() {
  741. luckysheet.destroy()
  742. this.loadReport()
  743. this.initCronList()
  744. },
  745. methods: {
  746. /** 实现类似刷新效果 */
  747. forceRefreshLuckysheet() {
  748. if (luckysheet) {
  749. luckysheet.setCellValue(49, 0, luckysheet.getCellValue(49, 0))
  750. }
  751. },
  752. sortChange({prop, order}) {
  753. this.reportDataList.sort(customCompare(prop, order))
  754. },
  755. sortChange1({prop, order}) {
  756. this.reportHistoryData.sort(customCompare(prop, order))
  757. },
  758. handleSizeChange(val) {
  759. this.reportPage = 1
  760. this.reportLimit = val
  761. this.loadReport()
  762. },
  763. handleCurrentChange(val) {
  764. this.reportPage = val
  765. this.loadReport()
  766. },
  767. sizeHistoryChangeEvent(val) {
  768. this.reportHistoryPage = 1
  769. this.reportHistoryLimit = val
  770. this.historyReport()
  771. },
  772. currentHistoryChangeEvent(val) {
  773. this.reportHistoryPage = val
  774. this.historyReport()
  775. },
  776. changeReportTypeEvent(val) {
  777. this.reportPage = 1
  778. this.searchValue = val
  779. this.loadReport()
  780. },
  781. searchReportEvent() {
  782. this.reportPage = 1
  783. this.loadReport()
  784. },
  785. validCron(value) {
  786. const cronParse = require('cron-parser')
  787. try {
  788. const interval = cronParse.parseExpression(value)
  789. console.log('cronDate:', interval.next().toDate())
  790. return true
  791. } catch (e) {
  792. }
  793. return false
  794. },
  795. analysisCron() {
  796. if (!this.cronVal) return
  797. let s = this.cronVal.split(' ')
  798. if (s[0].indexOf('/') > -1) {
  799. this.radioByCron = 1
  800. this.radioByCronValS = s[0].split('/')[1]
  801. } else if (s[1].indexOf('/') > -1) {
  802. this.radioByCron = 2
  803. this.radioByCronValM = s[1].split('/')[1]
  804. } else if (s[2].indexOf('/') > -1) {
  805. this.radioByCron = 3
  806. this.radioByCronValH = s[2].split('/')[1]
  807. } else if (s[3] === '*') {
  808. this.radioByCron = 4
  809. this.radioByCronValD = s[2] + ':' + s[1] + ':' + s[0]
  810. } else {
  811. this.radioByCron = 5
  812. this.radioByCronValMo = s[3]
  813. this.radioByCronValMoD = s[2] + ':' + s[1] + ':' + s[0]
  814. }
  815. },
  816. getCron() {
  817. let result = null
  818. switch (this.radioByCron) {
  819. // 按每秒执行:0/2 * * * * ?
  820. case 1:
  821. if (Number.isInteger(this.radioByCronValS)) {
  822. result = '0/#{cron} * * * * ?'
  823. result = result.replace('#{cron}', this.radioByCronValS)
  824. }
  825. break
  826. // 按每分钟执行:0 0/2 * * * ?
  827. case 2:
  828. if (Number.isInteger(this.radioByCronValM)) {
  829. result = '0 0/#{cron} * * * ?'
  830. result = result.replace('#{cron}', this.radioByCronValM)
  831. }
  832. break
  833. // 按每小时执行:0 0 0/2 * * ?
  834. case 3:
  835. if (Number.isInteger(this.radioByCronValH)) {
  836. result = '0 0 0/#{cron} * * ?'
  837. result = result.replace('#{cron}', this.radioByCronValH)
  838. }
  839. break
  840. // 每天定时执行:0 15 10 * * ?
  841. case 4:
  842. if (this.radioByCronValD) {
  843. let times = this.radioByCronValD.split(':')
  844. result = '#{cron1} #{cron2} #{cron3} * * ?'
  845. result = result.replace('#{cron1}', times[2])
  846. result = result.replace('#{cron2}', times[1])
  847. result = result.replace('#{cron3}', times[0])
  848. result = result.replace(/00/g, '0')
  849. }
  850. break
  851. // 每月定时执行:0 0 2 1 * ?
  852. case 5:
  853. if (Number.isInteger(this.radioByCronValMo) && this.radioByCronValMoD) {
  854. let times = this.radioByCronValMoD.split(':')
  855. result = '#{cron1} #{cron2} #{cron3} #{cron4} * ?'
  856. result = result.replace('#{cron1}', times[2])
  857. result = result.replace('#{cron2}', times[1])
  858. result = result.replace('#{cron3}', times[0])
  859. result = result.replace('#{cron4}', this.radioByCronValMo)
  860. result = result.replace(/00/g, '0')
  861. }
  862. break
  863. default:
  864. break
  865. }
  866. return result
  867. },
  868. chooseCronEvent() {
  869. this.cronVal = this.getCron()
  870. if (!this.cronVal) {
  871. this.$message({
  872. message: '请指定定时任务类型或运行时间!',
  873. type: 'warning'
  874. })
  875. return
  876. }
  877. if (!this.validCron(this.cronVal)) {
  878. this.$message({
  879. message: '定时任务表达式格式不正确,请检查!',
  880. type: 'warning'
  881. })
  882. return
  883. }
  884. const loading = showLoading(this, '请稍候···')
  885. let params = {
  886. 'id': this.reportId,
  887. 'isAutoReport': '1',
  888. 'cron': this.cronVal
  889. }
  890. tableExchangeTypeById(params).then(res => {
  891. loading.close()
  892. this.dialogClose()
  893. this.loadReport()
  894. }).catch((e) => {
  895. loading.close()
  896. showAlertWin(this, e)
  897. })
  898. },
  899. resetRadioVal() {
  900. this.radioByCron = null
  901. this.radioByCronValS = ''
  902. this.radioByCronValM = ''
  903. this.radioByCronValH = ''
  904. this.radioByCronValD = null
  905. this.radioByCronValMo = ''
  906. this.radioByCronValMoD = null
  907. this.cronVal = ''
  908. },
  909. chooseReportTypeEvent() {
  910. if (!this.reportType) {
  911. this.$message({
  912. message: '请选择报表类型!',
  913. type: 'warning'
  914. })
  915. }
  916. // 自动报表
  917. if (this.reportType == '1') {
  918. this.resetRadioVal()
  919. getReportTableById(this.reportId).then(res => {
  920. this.dialogAutoReportVisible = true
  921. this.cronVal = res.data.cron
  922. this.analysisCron()
  923. }).catch((e) => {
  924. showAlertWin(this, e)
  925. })
  926. return
  927. }
  928. const loading = showLoading(this, '请稍候···')
  929. let params = {
  930. 'id': this.reportId,
  931. 'isAutoReport': this.reportType
  932. }
  933. tableExchangeTypeById(params).then(res => {
  934. loading.close()
  935. this.dialogClose()
  936. this.loadReport()
  937. }).catch((e) => {
  938. loading.close()
  939. showAlertWin(this, e)
  940. })
  941. },
  942. switchChangeEvent(val, data) {
  943. this.reportId = data.id
  944. if (val) {
  945. this.resetRadioVal()
  946. this.dialogAutoReportVisible = true
  947. getReportTableById(data.id).then(res => {
  948. this.cronVal = res.data.cron
  949. this.analysisCron()
  950. }).catch((e) => {
  951. showAlertWin(this, e)
  952. })
  953. return
  954. }
  955. this.dialogReportTypeVisible = true
  956. },
  957. setReportStatus(data) {
  958. this.reportId = data.id
  959. this.reportType = data.isAutoReport + ''
  960. this.dialogReportTypeVisible = true
  961. },
  962. resetReportFormVal() {
  963. this.reportForm = {
  964. reportTemplate: null,
  965. reportValueFormat: '0', // 时间取值格式0时,1日,2月
  966. isAutoReport: 0,
  967. valueCondition: null, // 报表取值条件:0平均值 1最大值 2最小值 3瞬时值
  968. reportDate: [getNowFormatDate('yyyy-MM-dd') + ' 09:00:00',
  969. getNowFormatDate('yyyy-MM-dd') + ' 18:00:00']
  970. }
  971. },
  972. /** 新增报表 */
  973. addReportEvent() {
  974. this.resetReportFormVal()
  975. this.getAllReportTemplate()
  976. this.dialogReportTemplateVisible = true
  977. },
  978. /** 刷新报表 */
  979. refreshReportEvent() {
  980. this.reportPage = 1
  981. this.loadReport()
  982. },
  983. /** 模版报表选择 */
  984. chooseReportEvent() {
  985. this.$refs['reportForm'].validate((valid) => {
  986. if (valid) {
  987. const loading = showLoading(this, '数据加载中,请稍候···')
  988. getTableTemplateById(this.reportForm.reportTemplate).then(res => {
  989. if (!res.data) {
  990. loading.close()
  991. this.$message({
  992. message: '选择的报表模板不存在!',
  993. type: 'warning'
  994. })
  995. return
  996. }
  997. this.showMainView = true
  998. let luckyData = JSON.parse(res.data.templateData)
  999. this.chooseReportTemplateId = res.data.id
  1000. this.chooseIsAutoReport = this.reportForm.isAutoReport
  1001. this.chooseReportTemplate = luckyData
  1002. this.drawLuckyExcel(luckyData, () => {
  1003. loading.close()
  1004. this.dialogReportTemplateVisible = false
  1005. this.breadcrumbList = ['新增报表']
  1006. setTimeout(() => {
  1007. this.btnType = 'add'
  1008. }, 100)
  1009. })
  1010. }).catch((e) => {
  1011. loading.close()
  1012. showAlertWin(this, e)
  1013. })
  1014. }
  1015. })
  1016. },
  1017. /** 根据 ID 查询数据模型 */
  1018. getDataModelById(loading, reportData) {
  1019. if (!loading) {
  1020. loading = showLoading(this, '数据加载中,请稍候···')
  1021. }
  1022. getDataModelById(this.reportForm.operationRule).then(res => {
  1023. loading.close()
  1024. if (!res.data) {
  1025. this.$message({
  1026. message: '选择的四则运算表达式不存在!',
  1027. type: 'warning'
  1028. })
  1029. return
  1030. }
  1031. let luckyData = JSON.parse(reportData.templateData)
  1032. this.drawLuckyExcel(luckyData)
  1033. this.btnType = 'add'
  1034. this.dialogReportTemplateVisible = false
  1035. }).catch((e) => {
  1036. loading.close()
  1037. showAlertWin(this, e)
  1038. })
  1039. },
  1040. /** 绘制 Excel 表 */
  1041. drawLuckyExcel(luckyData, callback) {
  1042. let _this = this
  1043. luckysheet.destroy()
  1044. let option = luckyData.option
  1045. option.data = luckyData.data
  1046. let charts = luckyData.charts
  1047. let tables = luckyData.tables
  1048. option.hook = {
  1049. workbookCreateAfter() {
  1050. console.log(luckyData)
  1051. for (let i in charts) {
  1052. _this.insertEChartInfo(charts[i])
  1053. }
  1054. for (let i in tables) {
  1055. _this.insertTableInfo(tables[i])
  1056. }
  1057. _this.drawBaseInfo()
  1058. if (callback) {
  1059. callback()
  1060. }
  1061. },
  1062. cellUpdated(r, c, newV, oldV) {
  1063. if (!(r === 49 && c === 0)) {
  1064. _this.forceRefreshLuckysheet()
  1065. }
  1066. }
  1067. }
  1068. luckysheet.create(option)
  1069. },
  1070. /** 获取图表数据 */
  1071. getChartData(data, callback) {
  1072. getChartData(data).then(res => {
  1073. if (!res.data) {
  1074. if (callback) callback([])
  1075. return
  1076. }
  1077. if (callback) callback(res.data)
  1078. }).catch((e) => {
  1079. if (callback) callback([])
  1080. showAlertWin(this, e)
  1081. })
  1082. },
  1083. /** 获取表格数据 */
  1084. getTableData(data, callback) {
  1085. getTableData(data).then(res => {
  1086. if (!res.data) {
  1087. if (callback) callback([])
  1088. return
  1089. }
  1090. if (callback) callback(res.data)
  1091. }).catch((e) => {
  1092. if (callback) callback([])
  1093. showAlertWin(this, e)
  1094. })
  1095. },
  1096. /** 向 Excel 插入表格 */
  1097. insertTableInfo(tableData) {
  1098. let params = []
  1099. let itemList = tableData.item
  1100. for (let i in itemList) {
  1101. let temp = itemList[i]
  1102. params.push({
  1103. 'itemGroupId': temp.itemGroupId,
  1104. 'itemName': temp.itemName
  1105. })
  1106. }
  1107. let p = {
  1108. 'reportValueFormat': this.reportForm.reportValueFormat,
  1109. 'valueCondition': this.reportForm.valueCondition,
  1110. 'tableDataDtoChList': params,
  1111. 'showType': tableData.showType
  1112. }
  1113. if (this.reportForm.reportDate && this.reportForm.reportDate.length > 0) {
  1114. p.startBelongTime = this.reportForm.reportDate[0]
  1115. p.endBelongTime = this.reportForm.reportDate[1]
  1116. } else {
  1117. p.startBelongTime = getNowFormatDate('yyyy-MM-dd') + ' 08:00:00'
  1118. p.endBelongTime = getNowFormatDate('yyyy-MM-dd') + ' 18:00:00'
  1119. }
  1120. this.getTableData(p, (res) => {
  1121. // console.log('option==>', luckysheet.getAllSheets()[0])
  1122. // console.log('table1==>', res)
  1123. // const optionData = packtable(res, luckysheet.getAllSheets()[0])
  1124. // console.log('table2==>', optionData)
  1125. setTimeout(() => {
  1126. this.drawTableData(res, p.showType, luckysheet.getAllSheets()[0])
  1127. }, 500)
  1128. })
  1129. },
  1130. drawBaseInfo() {
  1131. let currDate = getNowFormatDate('yyyy-MM-dd')
  1132. let currDateTime = getNowFormatDate('yyyy-MM-dd HH:mm:ss')
  1133. let option = luckysheet.getAllSheets()[0]
  1134. option.celldata.map(item => {
  1135. if (item.v.v) {
  1136. item.v.v = String(item.v.v).trim();
  1137. if (item.v.v.match(/\${([^}]+)}/g)) { // 替换${xxx}内部数据
  1138. if (item.v.v.indexOf('${currDate}') > -1) {
  1139. let val = item.v.v
  1140. val = val.replace('${currDate}', currDate)
  1141. luckysheet.setCellValue(item.r, item.c, val)
  1142. }
  1143. if (item.v.v.indexOf('${currDateTime}') > -1) {
  1144. let val = item.v.v
  1145. val = val.replace('${currDateTime}', currDateTime)
  1146. luckysheet.setCellValue(item.r, item.c, val)
  1147. }
  1148. if (item.v.v.indexOf('${userName}') > -1) {
  1149. let val = item.v.v
  1150. val = val.replace('${userName}', getUsername())
  1151. luckysheet.setCellValue(item.r, item.c, val)
  1152. }
  1153. if (item.v.v.indexOf('${winUserName}') > -1) {
  1154. let val = item.v.v
  1155. val = val.replace('${winUserName}', process.env.VUE_APP_WINNAME)
  1156. luckysheet.setCellValue(item.r, item.c, val)
  1157. }
  1158. }
  1159. }
  1160. })
  1161. },
  1162. drawTableData(sources, type, option) {
  1163. option.celldata.map(item => {
  1164. if (item.v.v) {
  1165. item.v.v = String(item.v.v).trim();
  1166. if (item.v.v.match(/\${([^}]+)}/g)) { // 替换${xxx}内部数据
  1167. sources.forEach(source => {
  1168. let itemName = source.itemName
  1169. itemName = itemName.substring(itemName.lastIndexOf('.') + 1)
  1170. let name = '${' + source.itemGroupId + '.' + itemName + '.' + type.dataId + '}'
  1171. if (item.v.v === name) {
  1172. let dataList = source.dataList
  1173. // for (let i = 0; i < dataList.length; i++) {
  1174. for (let i = 0; i < type.valLine; i++) {
  1175. let p_r = parseInt(item.r)
  1176. let p_c = parseInt(item.c)
  1177. if (type.valType == '2') p_r += i
  1178. else p_c += i
  1179. luckysheet.setCellValue(p_r, p_c, (dataList[i] != null && dataList[i] != undefined) ? dataList[i] : '')
  1180. }
  1181. }
  1182. })
  1183. }
  1184. }
  1185. })
  1186. },
  1187. /** 向 Excel 插入图表 */
  1188. insertEChartInfo(chart) {
  1189. let _self = this
  1190. let info = chart.info
  1191. let itemList = chart.item
  1192. let itemArr = []
  1193. for (let i in itemList) {
  1194. let temp = itemList[i]
  1195. itemArr.push({
  1196. 'itemGroupId': temp.itemGroupId,
  1197. 'id': temp.id,
  1198. 'itemName': temp.itemName
  1199. })
  1200. }
  1201. let params = {
  1202. 'type': info.option.series[0].type,
  1203. 'valueCondition': this.reportForm.valueCondition,
  1204. 'chartTimeType': this.reportForm.reportValueFormat,
  1205. 'tableDataDtoChList': itemArr
  1206. }
  1207. if (this.reportForm.reportDate && this.reportForm.reportDate.length > 0) {
  1208. params.startBelongTime = this.reportForm.reportDate[0]
  1209. params.endBelongTime = this.reportForm.reportDate[1]
  1210. } else {
  1211. params.startBelongTime = getNowFormatDate('yyyy-MM-dd') + ' 08:00:00'
  1212. params.endBelongTime = getNowFormatDate('yyyy-MM-dd') + ' 18:00:00'
  1213. }
  1214. this.getChartData(params, (res) => {
  1215. let result = (res instanceof Array) ? res : []
  1216. // 系列
  1217. let series = info.option.series
  1218. for (let i in series) {
  1219. let temp = series[i]
  1220. temp.data = []
  1221. for (let j in result) {
  1222. if (params.type == 'pie') {
  1223. temp.name = result[j].name
  1224. temp.data.push({
  1225. 'name': result[j].describe ? result[j].describe : result[j].name,
  1226. 'value': result[j].value
  1227. })
  1228. } else {
  1229. temp.data = result[i].dataList ? result[i].dataList : []
  1230. }
  1231. }
  1232. }
  1233. if (params.type != 'pie') {
  1234. // x 轴
  1235. let xAxis = info.option.xAxis
  1236. let legend = info.option.legend
  1237. // xAxis.data = []
  1238. legend.data = []
  1239. xAxis.data = (result && result.length > 0) ? result[0].dataTimeList : []
  1240. xAxis.data = xAxis.data.slice(0, 7)
  1241. for (let i in result) {
  1242. let name = result[i].describe ? result[i].describe : result[i].itemName
  1243. // xAxis.data.push(name)
  1244. legend.data.push(name)
  1245. }
  1246. }
  1247. console.log(params.type, info)
  1248. setTimeout(() => {
  1249. const sheet = luckysheet.getLuckysheetfile()[0]
  1250. let optionData = sheet.data
  1251. try {
  1252. let flag = true
  1253. insertLuckysheetEChart({
  1254. selector: '#luckysheet',
  1255. info,
  1256. sheet,
  1257. optionData,
  1258. echarts,
  1259. luckysheet,
  1260. $,
  1261. _self,
  1262. flag
  1263. })
  1264. } catch (e) {
  1265. console.log(999, e == 'echarts is not defined')
  1266. console.error(e)
  1267. }
  1268. }, 200)
  1269. })
  1270. },
  1271. /** 查询所有报表信息 */
  1272. getAllReportTemplate() {
  1273. const loading = showLoading(this, '数据加载中,请稍候···')
  1274. let params = {
  1275. 'page': 1,
  1276. 'limit': 1000
  1277. }
  1278. getAllTableTemplate(params).then(res => {
  1279. loading.close()
  1280. if (!res.data) {
  1281. return
  1282. }
  1283. this.reportTemplateList = res.data.tableTemplateList
  1284. }).catch((e) => {
  1285. loading.close()
  1286. showAlertWin(this, e)
  1287. })
  1288. },
  1289. /** 查询所有数据模型 */
  1290. getAllDataModel() {
  1291. let params = {
  1292. 'page': 1,
  1293. 'limit': 1000
  1294. }
  1295. getAllDataModel(params).then(res => {
  1296. if (!res.data) {
  1297. return
  1298. }
  1299. this.dataModelList = res.data.dataModelList
  1300. }).catch((e) => {
  1301. showAlertWin(this, e)
  1302. })
  1303. },
  1304. /** 查询我的报表列表 */
  1305. loadReport() {
  1306. const loading = showLoading(this, '加载中,请稍候···')
  1307. let params = {
  1308. 'page': this.reportPage,
  1309. 'limit': this.reportLimit
  1310. }
  1311. if (this.searchValue != '-1') {
  1312. params.isAutoReport = this.searchValue
  1313. }
  1314. if (this.searchTxt && this.searchTxt.trim()) {
  1315. params.reportTableName = this.searchTxt
  1316. }
  1317. // getAllReportTable(params).then(res => {
  1318. getAllOkReportTable(params).then(res => {
  1319. loading.close()
  1320. if (!res || !res.data) {
  1321. return
  1322. }
  1323. this.reportTotal = res.data.count
  1324. this.reportDataList = res.data.reportTableList
  1325. }).catch((e) => {
  1326. loading.close()
  1327. showAlertWin(this, e)
  1328. })
  1329. },
  1330. /** 设置用户组信息 */
  1331. setUserGroupEvent(data) {
  1332. if (data.userId != this.uid) {
  1333. this.$message({
  1334. message: '您没有权限进行设置!',
  1335. type: 'warning'
  1336. })
  1337. return
  1338. }
  1339. this.reportId = data.id
  1340. this.dialogUserGroupVisible = true
  1341. getAllUserGroup().then(res => {
  1342. this.$nextTick(() => {
  1343. this.userGroupList = res.data
  1344. // this.userGroupInfo = data.userGroupList
  1345. this.userGroupInfo = []
  1346. for (let i = 0; i < data.userGroupList.length; i++) {
  1347. this.userGroupInfo.push(data.userGroupList[i].id)
  1348. }
  1349. if (data.userGroupList && data.userGroupList.length > 0) {
  1350. this.hasUserGroup = true
  1351. }
  1352. })
  1353. }).catch((e) => {
  1354. showAlertWin(this, e)
  1355. })
  1356. },
  1357. getUserGroupEvent(data) {
  1358. this.groupUserData = []
  1359. if (!data.userGroupList || data.userGroupList.length == 0) {
  1360. this.$message({
  1361. message: '该报表还未进行授权操作!',
  1362. type: 'warning'
  1363. })
  1364. return
  1365. }
  1366. let _this = this
  1367. data.userGroupList.forEach((group) => {
  1368. getUserByGroupId(group.id).then(res => {
  1369. let users = res.data
  1370. users.forEach((u) => {
  1371. _this.groupUserData.push({
  1372. 'userGroupName': group.userGroupName,
  1373. 'userName': u.userName
  1374. })
  1375. })
  1376. }).catch((e) => {
  1377. showAlertWin(_this, e)
  1378. })
  1379. })
  1380. this.dialogGroupUserVisible = true
  1381. },
  1382. chooseUserGroupEvent() {
  1383. // if (!this.userGroupInfo) {
  1384. // this.$message({
  1385. // message: '请选择用户组!',
  1386. // type: 'warning'
  1387. // })
  1388. // return
  1389. // }
  1390. let params = {
  1391. 'id': this.reportId,
  1392. 'userGroupList': []
  1393. }
  1394. for (let i = 0; i < this.userGroupInfo.length; i++) {
  1395. params.userGroupList.push({
  1396. 'id': this.userGroupInfo[i]
  1397. })
  1398. }
  1399. tableAssignUserById(params).then(res => {
  1400. if (this.hasUserGroup || this.userGroupInfo) {
  1401. this.$message({
  1402. message: '保存成功!',
  1403. type: 'success'
  1404. })
  1405. this.hasUserGroup = false
  1406. }
  1407. this.dialogClose()
  1408. this.loadReport()
  1409. }).catch((e) => {
  1410. showAlertWin(this, e)
  1411. })
  1412. },
  1413. /** 处理自动报表数据信息 */
  1414. drawAutoReportData(datas) {
  1415. if (!datas || datas.length == 0) {
  1416. return
  1417. }
  1418. datas.forEach((data) => {
  1419. if (!data || !data.item) {
  1420. return
  1421. }
  1422. let showInfo = data.showType
  1423. let fieldList = data.field
  1424. data.item.forEach((item, i) => {
  1425. if (!item || !item.dataList) {
  1426. return
  1427. }
  1428. let itemName = item.itemName
  1429. itemName = itemName.substring(itemName.lastIndexOf('.') + 1)
  1430. let tempName = '${' + item.itemGroupId + '.' + itemName + '.' + showInfo.dataId + '}'
  1431. let p_r, p_c
  1432. if (fieldList[i] && tempName == fieldList[i].name) {
  1433. p_r = parseInt(fieldList[i].r)
  1434. p_c = parseInt(fieldList[i].c)
  1435. } else {
  1436. for (let n = 0; n < fieldList.length; n++) {
  1437. if (fieldList[n].name == tempName) {
  1438. p_r = parseInt(fieldList[n].r)
  1439. p_c = parseInt(fieldList[n].c)
  1440. break
  1441. }
  1442. }
  1443. }
  1444. // 数据信息
  1445. let dataList = item.dataList
  1446. for (let j = 0; j < showInfo.valLine; j++) {
  1447. let c = p_c
  1448. let r = p_r
  1449. if (showInfo.valType == '2') r += j
  1450. else c += j
  1451. luckysheet.setCellValue(r, c, (dataList[j] != null && dataList[j] != undefined) ? (dataList[j] + '') : '')
  1452. }
  1453. })
  1454. })
  1455. },
  1456. /** 报表点击事件 */
  1457. handleReportNodeClick(data, type) {
  1458. if (data.id == -1 || this.delFlag == 1) {
  1459. return
  1460. }
  1461. const loading = showLoading(this, '加载中,请稍候···')
  1462. getReportTableById(data.id).then(res => {
  1463. loading.close()
  1464. if (!res.data) {
  1465. this.$message({
  1466. message: '选择的报表不存在!',
  1467. type: 'warning'
  1468. })
  1469. return
  1470. }
  1471. this.showMainView = true
  1472. this.breadcrumbList = [res.data.reportTableName]
  1473. let reportTableData = res.data.reportTableData
  1474. this.reportForm.valueCondition = res.data.valueCondition
  1475. this.reportForm.reportValueFormat = res.data.reportValueFormat
  1476. let luckyData = JSON.parse(reportTableData)
  1477. console.log(luckyData)
  1478. // 只读
  1479. if (type === 'history') {
  1480. this.dialogHistoryReportVisible = false
  1481. this.btnType = 'showChild'
  1482. } else if (type === 'deny') {
  1483. this.chooseMyReport = res.data
  1484. this.dialogHistoryReportVisible = false
  1485. this.btnType = 'showShared'
  1486. } else {
  1487. this.chooseMyReport = res.data
  1488. this.btnType = 'show'
  1489. }
  1490. this.setLuckysheetStatus(luckyData, type === 'history' || type === 'deny', type)
  1491. }).catch((e) => {
  1492. loading.close()
  1493. showAlertWin(this, e)
  1494. })
  1495. },
  1496. /** 设置工作表状态 */
  1497. setLuckysheetStatus(luckyData, isReadOnly, type) {
  1498. let _this = this
  1499. luckysheet.destroy()
  1500. let option = luckyData.option
  1501. if (!option) option = JSON.parse(JSON.stringify(this.luckysheetOption))
  1502. option.data = luckyData.data
  1503. if (isReadOnly) {
  1504. // 设置工作表保护
  1505. option.data[0].config.authority = {
  1506. sheet: 1, // 如果为 1 或 true,则该工作表受到保护;如果为 0 或 false,则该工作表不受保护。
  1507. hintText: '该工作表受到保护,无法操作', // 弹窗提示的文字
  1508. }
  1509. // 关闭右键菜单
  1510. option.cellRightClickConfig.chart = false
  1511. option.cellRightClickConfig.columnWidth = false
  1512. option.cellRightClickConfig.rowHeight = false
  1513. option.cellRightClickConfig.deleteColumn = false
  1514. option.cellRightClickConfig.deleteRow = false
  1515. option.cellRightClickConfig.insertColumn = false
  1516. option.cellRightClickConfig.insertRow = false
  1517. // 关闭工具栏
  1518. option.showtoolbar = false
  1519. option.enableAddRow = false
  1520. option.showtoolbarConfig = {
  1521. bold: false,
  1522. border: false,
  1523. fillColor: false,
  1524. font: false,
  1525. fontSize: false,
  1526. function: false,
  1527. horizontalAlignMode: false,
  1528. italic: false,
  1529. mergeCell: false,
  1530. moreFormats: false,
  1531. paintFormat: false,
  1532. strikethrough: false,
  1533. textColor: false,
  1534. underline: false,
  1535. verticalAlignMode: false
  1536. }
  1537. // 钩子函数
  1538. option.hook = {
  1539. workbookCreateAfter() {
  1540. let charts = luckyData.charts
  1541. let tables = luckyData.tables
  1542. let eventTables = luckyData.eventTables
  1543. option.data.forEach((data, i) => {
  1544. if (data.chart && data.chart.length > 0) {
  1545. data.chart.forEach((chart, j) => {
  1546. console.log(chart.chart_id)
  1547. let dom = document.getElementById(chart.chart_id + '_c')
  1548. if (dom) dom.style.display = 'none'
  1549. })
  1550. }
  1551. })
  1552. if (type == 'deny') {
  1553. for (let i in charts) {
  1554. _this.insertEChartInfo(charts[i])
  1555. }
  1556. for (let i in tables) {
  1557. _this.insertTableInfo(tables[i])
  1558. }
  1559. _this.drawBaseInfo()
  1560. }
  1561. _this.drawAutoReportData(luckyData.tables)
  1562. // 事件驱动报表信息
  1563. _this.drawEventReportData(eventTables)
  1564. luckysheet.setRangeShow('BH1')
  1565. }
  1566. }
  1567. } else {
  1568. let charts = luckyData.charts
  1569. let tables = luckyData.tables
  1570. let eventTables = luckyData.eventTables
  1571. // 钩子函数
  1572. option.hook = {
  1573. workbookCreateAfter() {
  1574. for (let i in charts) {
  1575. _this.insertEChartInfo(charts[i])
  1576. }
  1577. for (let i in tables) {
  1578. _this.insertTableInfo(tables[i])
  1579. }
  1580. _this.drawBaseInfo()
  1581. // 事件驱动报表信息
  1582. _this.drawEventReportData(eventTables)
  1583. luckysheet.setRangeShow('BH1')
  1584. },
  1585. cellUpdated(r, c, newV, oldV) {
  1586. if (!(r === 49 && c === 0)) {
  1587. _this.forceRefreshLuckysheet()
  1588. }
  1589. }
  1590. }
  1591. }
  1592. luckysheet.create(option)
  1593. },
  1594. /** 绘制事件驱动报表信息 */
  1595. drawEventReportData(eventTables) {
  1596. if (!eventTables || eventTables.length == 0) {
  1597. return
  1598. }
  1599. let x = 0, y = 0
  1600. eventTables.forEach((data, i) => {
  1601. x += 1
  1602. y = 0
  1603. let { dataList, dataTimeList, itemName } = data
  1604. itemName = (itemName != null && itemName != undefined) ? itemName : ''
  1605. luckysheet.setCellValue(x, y, itemName)
  1606. dataList.forEach((val, j) => {
  1607. y = j + 1
  1608. let _date = luckysheet.getCellValue(0, y)
  1609. if (!_date) {
  1610. let text = (dataTimeList[j] != null && dataTimeList[j] != undefined) ? dataTimeList[j] : ''
  1611. if (text.length > 19) text = text.substring(0, 19)
  1612. luckysheet.setCellValue(0, y, text)
  1613. }
  1614. val = (val != null && val != undefined) ? val : ''
  1615. luckysheet.setCellValue(x, y, val)
  1616. })
  1617. })
  1618. },
  1619. /** 修改报表信息 */
  1620. editReportItem(data) {
  1621. showPromptWin(this, '修改报表名称', '请输入报表名称', data.reportTableName, (val) => {
  1622. if (!val || !val.trim()) {
  1623. return '报表名称不能为空'
  1624. }
  1625. if (val.length > 20) {
  1626. return '报表名称必须在20字以内'
  1627. }
  1628. }, (value) => {
  1629. const loading = showLoading(this, '修改中,请稍候···')
  1630. let params = {
  1631. 'id': data.id,
  1632. 'reportTableName': value
  1633. }
  1634. updateTableNameById(params).then(res => {
  1635. loading.close()
  1636. let msg = res.data ? '修改成功!' : '修改失败!'
  1637. let msgType = res.data ? 'success' : 'warning'
  1638. this.$message({
  1639. message: msg,
  1640. type: msgType
  1641. })
  1642. this.reportPage = 1
  1643. this.loadReport()
  1644. }).catch((e) => {
  1645. loading.close()
  1646. showAlertWin(this, e)
  1647. })
  1648. })
  1649. },
  1650. /** 报表移除 */
  1651. removeReportItem(data, type) {
  1652. showConfirmWin(this, null, '您确定要删除该报表吗?', () => {
  1653. const loading = showLoading(this, '删除中,请稍候···')
  1654. delReportTableById(data.id).then(res => {
  1655. loading.close()
  1656. let msg = res.data ? '删除成功!' : '删除失败!'
  1657. let msgType = res.data ? 'success' : 'warning'
  1658. this.$message({
  1659. message: msg,
  1660. type: msgType
  1661. })
  1662. if (type == 'record') {
  1663. this.reportHistoryPage = 1
  1664. this.historyReport()
  1665. return
  1666. }
  1667. this.reportPage = 1
  1668. this.loadReport()
  1669. this.cancelSaveReport()
  1670. }).catch((e) => {
  1671. loading.close()
  1672. showAlertWin(this, e)
  1673. })
  1674. })
  1675. },
  1676. /** 获取单元格大小 */
  1677. getCellSize(celldata, r, c, luckysheet) {
  1678. const {cs, rs} = celldata.data[r][c].mc
  1679. const rowhidden = celldata.config.rowhidden && Object.keys(celldata.config.rowhidden) || ''
  1680. const rowArr = []
  1681. for (let i = 0; i < rs; i++) {
  1682. let rowIndex = r + i
  1683. if (rowhidden.indexOf(String(rowIndex)) < 0) {
  1684. rowArr.push(rowIndex)
  1685. }
  1686. }
  1687. const colArr = []
  1688. for (let j = 0; j < cs; j++) {
  1689. colArr.push(c + j)
  1690. }
  1691. const totalHeight = Object.values(
  1692. luckysheet.getRowHeight(rowArr)
  1693. ).reduce((a, b) => a + b)
  1694. const totalWidth = Object.values(
  1695. luckysheet.getColumnWidth(colArr)
  1696. ).reduce((a, b) => a + b)
  1697. return {
  1698. w: totalWidth,
  1699. h: totalHeight
  1700. }
  1701. },
  1702. /** 获取图片位置 */
  1703. getImagePosition(num, arr) {
  1704. let index = 0
  1705. let minIndex
  1706. let maxIndex
  1707. for (let i = 0; i < arr.length; i++) {
  1708. if (num < arr[i]) {
  1709. index = i
  1710. break
  1711. }
  1712. }
  1713. if (index == 0) {
  1714. minIndex = 0
  1715. maxIndex = 1
  1716. } else if (index == arr.length - 1) {
  1717. minIndex = arr.length - 2
  1718. maxIndex = arr.length - 1
  1719. } else {
  1720. minIndex = index - 1
  1721. maxIndex = index
  1722. }
  1723. let min = arr[minIndex]
  1724. let max = arr[maxIndex]
  1725. let radio = Math.abs((num - min) / (max - min)) + index
  1726. return radio
  1727. },
  1728. /** 图表转换为图片 */
  1729. convertChart(luckyData) {
  1730. const optionData = luckysheet.getLuckysheetfile()[0]
  1731. let {
  1732. visibledatacolumn, // 所有行的位置
  1733. visibledatarow // 所有列的位置
  1734. } = optionData
  1735. // 动态图表
  1736. if (luckyData.charts && luckyData.charts.length > 0) {
  1737. luckyData.charts.forEach((chart, i) => {
  1738. let myChart = echarts.init(
  1739. document.getElementsByClassName(chart.info.className)[0]
  1740. )
  1741. let baseData = myChart.getConnectedDataURL({
  1742. type: 'png',
  1743. pixelRatio: 2,
  1744. backgroundColor: '#ffffff'
  1745. })
  1746. // luckysheet.cancelRangeMerge(chart.info.pos)
  1747. luckysheet.insertImage(baseData, {
  1748. rowIndex: chart.info.pos[0],
  1749. colIndex: chart.info.pos[1],
  1750. cellSize: this.getCellSize(optionData, chart.info.pos[0], chart.info.pos[1], luckysheet),
  1751. success: function () {
  1752. console.log("插入成功")
  1753. }
  1754. })
  1755. })
  1756. }
  1757. // 静态图表
  1758. if (luckyData.data && luckyData.data.length > 0) {
  1759. luckyData.data.forEach((data, i) => {
  1760. if (data.chart && data.chart.length > 0) {
  1761. data.chart.forEach((chart, j) => {
  1762. let myChart = echarts.init(
  1763. document.getElementById(chart.chart_id)
  1764. )
  1765. myChart.setOption(chart.chartOptions);
  1766. let baseData = myChart.getConnectedDataURL({
  1767. type: 'png',
  1768. pixelRatio: 2,
  1769. backgroundColor: '#ffffff'
  1770. })
  1771. let col_st = this.getImagePosition(chart.left, visibledatacolumn)
  1772. let row_st = this.getImagePosition(chart.top, visibledatarow)
  1773. luckysheet.insertImage(baseData, {
  1774. rowIndex: parseInt(row_st),
  1775. colIndex: parseInt(col_st),
  1776. cellSize: {
  1777. w: chart.width,
  1778. h: chart.height,
  1779. },
  1780. success: function () {
  1781. console.log("插入成功")
  1782. }
  1783. })
  1784. })
  1785. }
  1786. })
  1787. }
  1788. },
  1789. /** 处理日期显示数字问题 */
  1790. withDateData(excelData) {
  1791. if (!excelData) {
  1792. return
  1793. }
  1794. try {
  1795. excelData.map((item) => {
  1796. if (item) {
  1797. item.map((ll) => {
  1798. if (ll && ll.ct && ll.ct.t && ll.ct.t === 'd') {
  1799. ll.m = ll.m,
  1800. ll.v = ll.m,
  1801. ll.ct = {
  1802. fa: "@",
  1803. t: "s",
  1804. }
  1805. }
  1806. })
  1807. }
  1808. })
  1809. }catch (error){
  1810. console.log(error)
  1811. }
  1812. },
  1813. /** 保存报表信息 */
  1814. saveReportInfo() {
  1815. showPromptWin(this, '保存', '请输入报表名称', '', (val) => {
  1816. if (!val) {
  1817. return '报表名称不能为空'
  1818. }
  1819. if (val.length > 20) {
  1820. return '报表名称必须在20字以内'
  1821. }
  1822. }, (value) => {
  1823. if (!this.chooseReportTemplate) {
  1824. this.$message({
  1825. message: '请重新选择报表模板',
  1826. type: 'warning'
  1827. })
  1828. return
  1829. }
  1830. const loading = showLoading(this, '保存中,请稍候···')
  1831. let excelData = this.chooseReportTemplate.data[0].data
  1832. let excelTable = this.chooseReportTemplate.tables
  1833. excelTable.forEach(table => {
  1834. table.field.forEach(field => {
  1835. luckysheet.setCellValue(field.r, field.c, field.name)
  1836. })
  1837. })
  1838. this.withDateData(excelData)
  1839. // this.convertChart(this.chooseReportTemplate)
  1840. let data = {
  1841. 'tableTemplateId': this.chooseReportTemplateId,
  1842. 'reportTableName': value,
  1843. 'reportValueFormat': this.reportForm.reportValueFormat,
  1844. 'valueCondition': this.reportForm.valueCondition,
  1845. 'isAutoReport': this.chooseIsAutoReport,
  1846. 'reportTableData': JSON.stringify(this.chooseReportTemplate)
  1847. }
  1848. saveReport(data).then(res => {
  1849. loading.close()
  1850. let msg = res.data ? '保存成功!' : '保存失败!'
  1851. let msgType = res.data ? 'success' : 'error'
  1852. this.$message({
  1853. message: msg,
  1854. type: msgType
  1855. })
  1856. this.showMainView = false
  1857. this.loadReport()
  1858. this.cancelSaveReport()
  1859. }).catch((e) => {
  1860. loading.close()
  1861. showAlertWin(this, e)
  1862. })
  1863. })
  1864. },
  1865. /** 更新报表信息 */
  1866. updateReport() {
  1867. console.log(this.chooseMyReport)
  1868. if (!this.chooseMyReport || !this.chooseMyReport.id) {
  1869. this.$message({
  1870. message: '保存失败,请刷新后重试!',
  1871. type: 'warning'
  1872. })
  1873. return
  1874. }
  1875. showPromptWin(this, '保存', '请输入报表名称', this.chooseMyReport.reportTableName, (val) => {
  1876. if (!val) {
  1877. return '报表名称不能为空'
  1878. }
  1879. if (val.length > 20) {
  1880. return '报表名称必须在20字以内'
  1881. }
  1882. }, (value) => {
  1883. const loading = showLoading(this, '保存中,请稍候···')
  1884. let _data2 = JSON.parse(this.chooseMyReport.reportTableData)
  1885. let excelTable = _data2.tables
  1886. excelTable.forEach(table => {
  1887. table.field.forEach(field => {
  1888. luckysheet.setCellValue(field.r, field.c, field.name)
  1889. })
  1890. })
  1891. let _data = JSON.parse(getLuckysheetConfig())
  1892. let excelData = _data[0].data
  1893. this.withDateData(excelData)
  1894. _data2.data = _data
  1895. // this.convertChart(_data2)
  1896. let data = this.chooseMyReport
  1897. data.reportTableName = value
  1898. data.reportTableData = JSON.stringify(_data2)
  1899. updateReportTable(data).then(res => {
  1900. loading.close()
  1901. let msg = res.data ? '保存成功!' : '保存失败!'
  1902. let msgType = res.data ? 'success' : 'error'
  1903. this.$message({
  1904. message: msg,
  1905. type: msgType
  1906. })
  1907. this.showMainView = false
  1908. this.loadReport()
  1909. this.cancelSaveReport()
  1910. }).catch((e) => {
  1911. loading.close()
  1912. showAlertWin(this, e)
  1913. })
  1914. })
  1915. },
  1916. /** 报表下载 */
  1917. downloadReport() {
  1918. this.dialogDownloadReportTypeVisible = true
  1919. },
  1920. /** 报表下载事件 */
  1921. downloadReportEvent() {
  1922. if (!this.chooseMyReport) {
  1923. this.$message({
  1924. message: '请选择报表',
  1925. type: 'warning'
  1926. })
  1927. return
  1928. }
  1929. let reportName = this.chooseMyReport.reportTableName ? this.chooseMyReport.reportTableName : '统计报表'
  1930. if (this.downloadType == '1') {
  1931. // exportExcel(luckysheet, reportName, ExcelJS).then((res) => {
  1932. // console.log("result==>", res)
  1933. // // this.$message({
  1934. // // message: res,
  1935. // // type: 'success'
  1936. // // })
  1937. // this.dialogDownloadReportTypeVisible = false
  1938. // }).catch((err) => {
  1939. // })
  1940. exportExcel(luckysheet.getAllSheets(), reportName)
  1941. setTimeout(() => {
  1942. this.dialogDownloadReportTypeVisible = false
  1943. }, 500)
  1944. }
  1945. },
  1946. /** 报表记录 */
  1947. historyReport() {
  1948. const loading = showLoading(this, '加载中,请稍候···')
  1949. let params = {
  1950. 'page': this.reportHistoryPage,
  1951. 'limit': this.reportHistoryLimit,
  1952. 'autoTableId': this.chooseMyReport.id
  1953. }
  1954. getAutoChReportTable(params).then(res => {
  1955. loading.close()
  1956. this.dialogHistoryReportVisible = true
  1957. if (!res.data) return
  1958. this.reportHistoryData = res.data.reportTableList
  1959. this.reportHistoryTotal = res.data.count
  1960. }).catch((e) => {
  1961. loading.close()
  1962. showAlertWin(this, e)
  1963. })
  1964. },
  1965. getPrintSheetArea() {
  1966. const sheetData = luckysheet.getSheetData();
  1967. let objRowColumn = {
  1968. row: [0, 0], //行
  1969. column: [0, 0], //列
  1970. };
  1971. // * item是行、index是行索引、it是一行里的一格、itemIndex是这一格在这一行里的列索引
  1972. sheetData.forEach((item, index) => {
  1973. //行数
  1974. item.forEach((it, itemIndex) => {
  1975. if (it !== null && it.v) {
  1976. console.log(index, it)
  1977. if (objRowColumn.row[1] < index) {
  1978. objRowColumn.row[1] = index; //row第二位
  1979. }
  1980. if (objRowColumn.column[1] < itemIndex) {
  1981. objRowColumn.column[1] = itemIndex; //column第二位
  1982. }
  1983. }
  1984. });
  1985. });
  1986. return objRowColumn;
  1987. },
  1988. /** 打印操作 */
  1989. printExcel() {
  1990. const loading = showLoading(this, '请稍候···')
  1991. document.querySelector('#print-area').style = "display:block";
  1992. window.luckysheet.hideGridLines();
  1993. // 获取当前选中区域
  1994. let currentSelected = luckysheet.getRange()
  1995. // 如果当前选中区只是一个单元格,则认为选取无效。
  1996. if (currentSelected[0] != null
  1997. && (currentSelected[0].row[1] - currentSelected[0].row[0] >= 1
  1998. || currentSelected[0].column[1] - currentSelected[0].column[0] >= 1)) {
  1999. // 生成base64图片
  2000. let imgSrc = luckysheet.getScreenshot();
  2001. window.luckysheet.showGridLines();
  2002. // * Lodop中的ADD_PRINT_IMAGE,也可以直接输出base64码图片,不用加img标签(如果加了img标签,会被当做超文本对待,受浏览器引擎解析的影响)
  2003. let $img = `<img src=${imgSrc} style="max-width: 90%;" />`
  2004. this.$nextTick(() => {
  2005. document.querySelector('#print-html').innerHTML = $img;
  2006. setTimeout(() => {
  2007. Print({
  2008. printable: 'print-html',
  2009. type: 'html',
  2010. documentTitle: '文档标题',
  2011. header: '',
  2012. headerStyle: 'font-weight:400;text-align:center;',
  2013. style: '@page {margin: 0 10mm};', // 不打印页眉和页脚
  2014. honorColor: true, // 是否打印彩色文本
  2015. targetStyles: ['*'] // 允许打印所有样式属性
  2016. }) // Print.js插件
  2017. document.querySelector("#print-area").style.display = "none";
  2018. loading.close()
  2019. }, 1000)
  2020. })
  2021. } else {
  2022. // 获取打印区域的行列
  2023. let RowColumn = this.getPrintSheetArea();
  2024. // 因需要打印左边的边框,需重新设置第一列
  2025. RowColumn.column[0] = 0;
  2026. // 进行选区操作
  2027. luckysheet.setRangeShow(RowColumn);
  2028. let imgSrc = luckysheet.getScreenshot(); // 生成base64图片
  2029. window.luckysheet.showGridLines();
  2030. // * Lodop中的ADD_PRINT_IMAGE,也可以直接输出base64码图片,不用加img标签(如果加了img标签,会被当做超文本对待,受浏览器引擎解析的影响)
  2031. let $img = `<img src=${imgSrc} style="max-width: 90%;" />`
  2032. this.$nextTick(() => {
  2033. document.querySelector('#print-html').innerHTML = $img;
  2034. setTimeout(() => {
  2035. Print({
  2036. printable: 'print-html',
  2037. type: 'html',
  2038. documentTitle: '文档标题',
  2039. header: '',
  2040. headerStyle: 'font-weight:400;text-align:center;',
  2041. style: '@page {margin: 0 10mm};', // 不打印页眉和页脚
  2042. honorColor: true, // 是否打印彩色文本
  2043. targetStyles: ['*'] // 允许打印所有样式属性
  2044. }) // Print.js插件
  2045. document.querySelector("#print-area").style.display = "none";
  2046. loading.close()
  2047. }, 1000)
  2048. })
  2049. }
  2050. },
  2051. /** 自定义选中区域 */
  2052. getExcelRowColumn() {
  2053. const sheetData = luckysheet.getSheetData();
  2054. let objRowColumn = {
  2055. row: [null, null], //行
  2056. column: [null, null], //列
  2057. };
  2058. sheetData.forEach((item, index) => {
  2059. //行数
  2060. item.forEach((it, itemIndex) => {
  2061. console.log(it)
  2062. if (it !== null) {
  2063. if (objRowColumn.row[0] == null) objRowColumn.row[0] = index; // row第一位
  2064. objRowColumn.row[1] = index; //row第二位
  2065. if (objRowColumn.column[0] == null)
  2066. objRowColumn.column[0] = itemIndex; //column第一位
  2067. objRowColumn.column[1] = itemIndex; //column第二位
  2068. }
  2069. });
  2070. });
  2071. return objRowColumn;
  2072. },
  2073. cronNodeEvent(obj) {
  2074. this.cronVal = obj.value
  2075. },
  2076. initCronList() {
  2077. this.cronList = []
  2078. this.cronList.push({value: '0/2 * * * * ?', label: '表示每2秒钟执行一次任务'})
  2079. this.cronList.push({value: '0 0/2 * * * ?', label: '表示每2分钟执行一次任务'})
  2080. this.cronList.push({value: '0 0 0/2 * * ?', label: '表示每2小时执行一次任务'})
  2081. this.cronList.push({value: '0 15 10 * * ?', label: '表示在每天上午10点15分执行一次任务'})
  2082. this.cronList.push({value: '0 0 10,14,16 * * ?', label: '表示在每天的上午10点、下午2点、下午4点分别执行一次任务'})
  2083. this.cronList.push({
  2084. value: '0 0/30 9-17 * * ?',
  2085. label: '表示在每天的上午9点到下午5点的范围内每30分钟执行一次任务'
  2086. })
  2087. this.cronList.push({value: '0 0 12 ? * WED', label: '表示在每周星期三中午12点执行一次任务'})
  2088. this.cronList.push({value: '0 0 2 1 * ?', label: '表示在每月的1日的凌晨2点执行一次任务'})
  2089. },
  2090. /** 取消保存报表 */
  2091. cancelSaveReport2() {
  2092. this.handleReportNodeClick(this.chooseMyReport, this.chooseMyReport.userId !== this.uid ? 'deny' : '')
  2093. },
  2094. /** 取消保存报表 */
  2095. cancelSaveReport() {
  2096. luckysheet.destroy()
  2097. this.breadcrumbList = ['运行配置']
  2098. this.showMainView = false
  2099. this.btnType = ''
  2100. this.chooseMyReport = null
  2101. if (this.$refs['reportForm']) this.$refs['reportForm'].resetFields()
  2102. },
  2103. /** 弹出层关闭事件 */
  2104. dialogClose(done) {
  2105. this.cronVal = ''
  2106. this.reportId = null
  2107. // this.userGroupInfo = null
  2108. if (typeof (done) === 'function') {
  2109. done()
  2110. } else {
  2111. this.dialogReportTemplateVisible = false
  2112. this.dialogDownloadReportTypeVisible = false
  2113. this.dialogAutoReportVisible = false
  2114. this.dialogReportTypeVisible = false
  2115. this.dialogUserGroupVisible = false
  2116. }
  2117. },
  2118. /** 弹出层关闭事件 */
  2119. dialogGroupUserClose(done) {
  2120. if (typeof (done) === 'function') {
  2121. done()
  2122. } else {
  2123. this.dialogGroupUserVisible = false
  2124. }
  2125. }
  2126. }
  2127. }
  2128. </script>
  2129. <style rel="stylesheet/scss" lang="scss">
  2130. .breadcrumb-content {
  2131. padding-bottom: 0;
  2132. }
  2133. .cy-nav-sx {
  2134. float: left !important;
  2135. margin-top: -23px !important;
  2136. margin-left: 120px !important;
  2137. display: flex;
  2138. }
  2139. .cy-nav-btn {
  2140. float: right !important;
  2141. margin-right: 20px !important;
  2142. margin-top: -20px !important;
  2143. }
  2144. .cy-main {
  2145. margin: 10px 20px;
  2146. width: calc(100% - 40px);
  2147. height: calc(100% - 100px);
  2148. .cy-btn {
  2149. margin-bottom: 10px;
  2150. }
  2151. .cy-btn .el-link {
  2152. margin-right: 15px;
  2153. }
  2154. .cy-main-left {
  2155. width: 100%;
  2156. height: 100%;
  2157. overflow: auto;
  2158. //float: left;
  2159. padding: 5px 10px;
  2160. //border-right: 1px solid #d4d4d4;
  2161. .cy-list {
  2162. overflow: auto;
  2163. height: 100%;
  2164. height: calc(100% - 40px);
  2165. ul {
  2166. display: flex;
  2167. flex-wrap: wrap;
  2168. padding: 0;
  2169. margin-top: 0;
  2170. li {
  2171. list-style-type: none;
  2172. background: #41aed7;
  2173. width: 23%;
  2174. margin: 10px 1%;
  2175. border-radius: 8px;
  2176. height: 110px;
  2177. padding: 15px;
  2178. color: #ffffff;
  2179. .cy-item-name {
  2180. font-size: 14px;
  2181. text-overflow: ellipsis;
  2182. white-space: nowrap;
  2183. overflow: hidden;
  2184. margin-bottom: 15px;
  2185. cursor: pointer;
  2186. }
  2187. .cy-item-val {
  2188. font-size: 12px;
  2189. }
  2190. .cy-list-item {
  2191. font-size: 12px;
  2192. color: #f6f6f6;
  2193. width: 100%;
  2194. //display: flex;
  2195. margin-top: 40px;
  2196. }
  2197. }
  2198. }
  2199. }
  2200. }
  2201. .cy-main-right {
  2202. width: 100%;
  2203. height: 100%;
  2204. float: left;
  2205. overflow: hidden;
  2206. }
  2207. }
  2208. .cy-group-tree1 {
  2209. font-size: 14px;
  2210. .custom-tree-node1 {
  2211. height: 28px;
  2212. line-height: 28px;
  2213. }
  2214. }
  2215. .cron-txt {
  2216. color: blue;
  2217. margin-right: 20px;
  2218. cursor: pointer;
  2219. font-weight: bold;
  2220. font-size: 16px;
  2221. }
  2222. .cron-txt-desc {
  2223. }
  2224. .ug-div {
  2225. .el-transfer-panel {
  2226. width: 300px;
  2227. }
  2228. }
  2229. </style>