sheet.vue 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632
  1. <!--
  2. * @Author : yuanrunwei
  3. * @Date : 2021-12-04 14:23:58
  4. * @LastEditors: daiqisheng
  5. * @LastEditTime: 2022-05-10 11:24:05
  6. * @FilePath : \spfm-market-front\src\pages\main\performance\components\sheet.vue
  7. -->
  8. <template>
  9. <fullscreen id="containerClass" :fullscreen.sync="fullscreen" class="containerClass" style=" background-color: #ffffff">
  10. <div class="sheet-container" id="full-container">
  11. <div style=" margin-top: 20px; margin-left: 30px;" >
  12. <span style=" font-size: small;margin-right: 10px;">控制权限</span>
  13. <el-select v-model="state" placeholder="请选择" :disabled="this.type=='view'|| (this.type=='edit' && this.isCreater !='1') ?true:false " size="mini">
  14. <el-option
  15. v-for="item in options"
  16. :key="item.value"
  17. :label="item.label"
  18. :value="item.value">
  19. </el-option>
  20. </el-select>
  21. </div>
  22. <div class="flex-justify-align-end margin-bottom-20">
  23. <!-- <span-->
  24. <!-- v-if="['template'].includes(attribute)"-->
  25. <!-- ><span class="sheet-container-require">*</span>模板类型:</span-->
  26. <!-- >-->
  27. <div style="display: flex;
  28. margin-right: 20px;
  29. background: rgb(2, 135, 251);
  30. padding: 2px;
  31. border-radius: 4px;">
  32. <el-upload
  33. action
  34. :http-request="request"
  35. :on-change="handleChange"
  36. :show-file-list="false"
  37. :disabled="this.type=='view'?true:false"
  38. >
  39. <el-button :disabled="this.type=='view'?true:false" size="mini">选择文件</el-button>
  40. </el-upload>
  41. <span style="font-size: 12px;margin-right: 5px;line-height: 2;color: white;">{{ fileListName }}</span>
  42. </div>
  43. <el-button
  44. type="danger"
  45. @click="handleResave"
  46. size="mini"
  47. :disabled="this.type=='view'?true:false"
  48. >保存</el-button
  49. >
  50. <!-- :disabled="handleForbid()"-->
  51. <el-button size="mini" type="danger" @click="handleDownload">导出</el-button>
  52. <el-button size="mini" type="primary" @click="returnList">返回</el-button>
  53. <el-button size="mini" type="primary" @click="handleFullscreen">{{ showName }}</el-button>
  54. </div>
  55. <div id="luckysheet" class="sheet-container-block_class" ></div>
  56. </div>
  57. </fullscreen>
  58. </template>
  59. <script>
  60. import luckyexcel from "luckyexcel";
  61. import { exportExcel } from "./export";
  62. export default {
  63. components: {
  64. },
  65. props: {
  66. isCreater: {
  67. type: String,
  68. default: "",
  69. },
  70. type: {
  71. type: String,
  72. default: "view", // view 查看 edit 编辑
  73. },
  74. attribute: {
  75. type: String,
  76. default: "template", // template 模板 order 工单 file 文件
  77. },
  78. id: {
  79. default: null,
  80. },
  81. // 接收人
  82. receiver: {
  83. type: String,
  84. default: "",
  85. },
  86. // 模板状态按钮判断
  87. status: { type: String, default: "" },
  88. mkdirId:{
  89. type: String,
  90. default:'',
  91. },
  92. fullscreen:{
  93. type:Boolean,
  94. default:false
  95. },
  96. workName:{
  97. type:String
  98. },
  99. workData:{
  100. type:Object
  101. }
  102. },
  103. data() {
  104. return {
  105. options: [{
  106. value: '1',
  107. label: '开启'
  108. },{
  109. value: '0',
  110. label: '关闭'
  111. }],
  112. state:'1',
  113. form: {
  114. charge: [
  115. {
  116. person: [],
  117. col_start: "",
  118. col_end: "",
  119. row_start: "",
  120. row_end: "",
  121. },
  122. ],
  123. array: [],
  124. type: null,
  125. permission_type: null,
  126. col_start: "",
  127. col_end: "",
  128. row_start: "",
  129. row_end: "",
  130. },
  131. approveForm: {
  132. type: "",
  133. comments: "",
  134. list: [
  135. {
  136. label: "同意",
  137. value: "同意",
  138. },
  139. {
  140. label: "不同意",
  141. value: "不同意",
  142. },
  143. {
  144. label: "其他",
  145. value: "3",
  146. },
  147. ],
  148. },
  149. superviserules: {
  150. distribute: [
  151. { required: true, message: "请选择派发周期", trigger: "change" },
  152. ],
  153. write: [
  154. { required: true, message: "请选择填报周期", trigger: "change" },
  155. ],
  156. endTime: [
  157. { required: true, message: "请选择截止时间", trigger: "change" },
  158. ],
  159. },
  160. superviseForm: {
  161. distribute: "", // 派单周期
  162. write: "", // 填写周期
  163. endTime: "", // 截止时间
  164. },
  165. originSuperviseForm: {},
  166. pickOptions: {
  167. disabledDate(time) {
  168. return time.getTime() < new Date().getTime() - 8.64e7;
  169. },
  170. },
  171. pickWrite: {
  172. disabledDate(time) {
  173. return time.getTime() < new Date().getTime() - 8.64e7;
  174. },
  175. },
  176. // 可提交标志
  177. addFlag: "0",
  178. // 督办标志
  179. superviseFlag: null,
  180. rowList: [],
  181. isDisable: true,
  182. issued_id: null,
  183. template_id: null,
  184. visible: false,
  185. templateType: "",
  186. // 督办
  187. supervise: false,
  188. manager_approve: false,
  189. row_list: [],
  190. column_list: [],
  191. charge_list: [],
  192. type_options: [
  193. {
  194. value: 1,
  195. label: "按行",
  196. },
  197. // {
  198. // value: 2,
  199. // label: "按列",
  200. // },
  201. ],
  202. fileListName:'未选择任何文件',
  203. showName: '全屏显示'
  204. };
  205. },
  206. methods: {
  207. request(){},
  208. handleInit() {
  209. if (this.id) {
  210. if (this.workData){
  211. this.handleCreate({
  212. json: this.workData,
  213. name: this.workName,
  214. type: "json",
  215. });
  216. }else {
  217. this.handleQuery();
  218. }
  219. } else {
  220. if (this.workData){
  221. this.handleCreate({
  222. json: this.workData,
  223. name: this.workName,
  224. type: "json",
  225. });
  226. }else {
  227. this.handleCreate();
  228. }
  229. }
  230. if (this.fullscreen){
  231. this.$nextTick(()=>{
  232. this.handleFullscreenOption();
  233. this.showName = '退出全屏'
  234. })
  235. }
  236. },
  237. returnList(){
  238. if (this.fullscreen){
  239. this.handleFullscreenOption()
  240. this.$emit("handleFullscreen", false)
  241. }
  242. this.$emit("save");
  243. },
  244. handleAllow() {
  245. //查看无法编辑
  246. return this.type=="view"?false:true;
  247. },
  248. addInputPlace(){
  249. this.$nextTick(()=>{
  250. let element = document.getElementById('luckysheet_info_detail_input');
  251. element.placeholder = '请输入标题'
  252. element.style['min-width'] = '120px'
  253. })
  254. },
  255. async handleQuery() {
  256. const {
  257. data: {
  258. templateContent,
  259. templateName,
  260. state,
  261. },
  262. } = await this.$http({
  263. url: "/market/workLists/getWorkById",
  264. method: "post",
  265. headers: {
  266. "Content-Type": "application/json",
  267. },
  268. data: {id:this.id},
  269. });
  270. this.state=state;
  271. this.handleCreate({
  272. json: templateContent ? JSON.parse(templateContent) : {},
  273. name: templateName,
  274. type: "json",
  275. });
  276. },
  277. async handleCreate({ file, json, type, name } = {}) {
  278. let that = this;
  279. if('add'== this.type){
  280. window.luckysheet.destroy();
  281. window.luckysheet.create({
  282. container: "luckysheet",
  283. lang: "zh",
  284. showsheetbar: false,
  285. data:[{"name": "777e1d91-2075-446f-b163-03c5e0ee0e0c"}],
  286. plugins:['chart'],
  287. userInfo:undefined,
  288. title:""
  289. })
  290. this.addInputPlace();
  291. if (!this.fullscreen){
  292. let interval = setInterval(()=>{
  293. let elementById = document.getElementById("luckysheet-icon-morebtn-div");
  294. if (elementById){
  295. elementById.style.width = '55%'
  296. clearInterval(interval)
  297. }
  298. },300)
  299. }
  300. }
  301. switch (type) {
  302. case "file":
  303. if (file) {
  304. await new Promise((resolve) => {
  305. luckyexcel.transformExcelToLucky(file, (export_json) => {
  306. let name = export_json.info.name;
  307. if(!name.endsWith(".xlsx")){
  308. this.$message({
  309. type: "error",
  310. message: '导入失败!只支持.xlsx格式文件',
  311. });
  312. }else {
  313. this.fileListName = name;
  314. let lastIndexOf = export_json.info.name.lastIndexOf('.');
  315. name = name.substring(0, lastIndexOf);
  316. window.luckysheet.destroy();
  317. export_json.sheets.name = '777e1d91-2075-446f-b163-03c5e0ee0e0c'
  318. window.luckysheet.create({
  319. container: "luckysheet",
  320. lang: "zh",
  321. plugins:['chart'],
  322. showsheetbar: false,
  323. data:export_json.sheets,
  324. title:name,
  325. userInfo:export_json.info.name.creater
  326. })
  327. this.addInputPlace();
  328. if (!this.fullscreen){
  329. let interval = setInterval(()=>{
  330. let elementById = document.getElementById("luckysheet-icon-morebtn-div");
  331. if (elementById){
  332. elementById.style.width = '55%'
  333. clearInterval(interval)
  334. }
  335. },300)
  336. }
  337. }
  338. resolve();
  339. });
  340. });
  341. }
  342. break;
  343. case "json":
  344. if (json) {
  345. window.luckysheet.destroy();
  346. let data=[];
  347. data[0]=json;
  348. if('view'==this.type){
  349. window.luckysheet.create({
  350. container: "luckysheet",
  351. lang: "zh",
  352. plugins:['chart'],
  353. showsheetbar: false,
  354. data:data,
  355. title:name,
  356. userInfo:name.creater,
  357. hook: {
  358. cellEditBefore: function ([
  359. { row_focus: row, column_focus: column },
  360. ]) {
  361. if (!that.handleAllow({ row, column })) {
  362. that.$message.error("当前为【查看】状态,无法编辑!");
  363. }
  364. },
  365. // cellUpdated: function (row, column) {
  366. // that.rowList.push(row);
  367. // },
  368. cellUpdateBefore: function (row, column) {
  369. console.log(row, column);
  370. if (!that.handleAllow({ row, column })) {
  371. return false;
  372. }
  373. },
  374. rangePasteBefore: function ([
  375. { row_focus: row, column_focus: column },
  376. ]) {
  377. if (!that.handleAllow({ row, column })) {
  378. that.$message.error("当前为【查看】状态,无法编辑!");
  379. return false;
  380. }
  381. },
  382. updated: function ({ range }) {
  383. const middle = range.map((el) => {
  384. return that.paramsArr(el.row[0], el.row[1]);
  385. });
  386. let changedList = middle.join(",").split(",");
  387. that.rowList.push(...changedList);
  388. },
  389. }
  390. });
  391. }else{
  392. window.luckysheet.create({
  393. container: "luckysheet",
  394. lang: "zh",
  395. plugins:['chart'],
  396. showsheetbar: false,
  397. data:data,
  398. title:name,
  399. userInfo:name.creater
  400. });
  401. this.addInputPlace();
  402. if (!this.fullscreen){
  403. let interval = setInterval(()=>{
  404. let elementById = document.getElementById("luckysheet-icon-morebtn-div");
  405. if (elementById){
  406. elementById.style.width = '55%'
  407. clearInterval(interval)
  408. }
  409. },300)
  410. }
  411. }
  412. }
  413. break;
  414. }
  415. },
  416. async handleChange(response, fileList) {
  417. this.handleCreate({ file: response.raw, type: "file" });
  418. },
  419. handleDownload() {
  420. exportExcel(
  421. window.luckysheet.getAllSheets(),
  422. window.luckysheet.getWorkbookName()
  423. );
  424. },
  425. // 判断数组是否有值
  426. confirmArrayData(data) {
  427. if (data instanceof Array) {
  428. if (data.length) {
  429. for (let i = 0; i < data.length; i++) {
  430. if (data[i] instanceof Array){
  431. for (let j = 0; j < data[i].length; j++) {
  432. if ((data[i][j] && data[i][j].v) || (data[i][j] && data[i][j].ct && data[i][j].ct.s && data[i][j].ct.s.length > 0 && data[i][j].ct.s[0].v)) {
  433. return true;
  434. }
  435. }
  436. }else {
  437. return false;
  438. }
  439. }
  440. return false;
  441. } else {
  442. return false;
  443. }
  444. } else {
  445. return false;
  446. }
  447. },
  448. // 通用方法用于转化全局
  449. paramsArr(start, end) {
  450. const arr = [];
  451. console.log(start, end);
  452. for (let i = Number(start); i <= Number(end); i++) {
  453. arr.push(i);
  454. }
  455. return arr.join(",");
  456. },
  457. handleFullscreen() {
  458. const data = window.luckysheet.getSheet({name:"777e1d91-2075-446f-b163-03c5e0ee0e0c"});
  459. const workbook_name = window.luckysheet.getWorkbookName();
  460. this.$emit('saveData', workbook_name, data)
  461. if (this.fullscreen === false){
  462. this.$emit("handleFullscreen", true)
  463. }
  464. if (this.fullscreen === true){
  465. this.$emit("handleFullscreen", false)
  466. }
  467. },
  468. handleFullscreenOption(){
  469. const element = document.body;
  470. const is_fullscreen =
  471. document.fullScreen ||
  472. document.mozFullScreen ||
  473. document.webkitIsFullScreen;
  474. if (!is_fullscreen) {
  475. let elementById = document.getElementById("containerClass");
  476. elementById.style.height = 'calc(100vh - 100px)';
  477. //进入全屏,多重短路表达式
  478. (element.requestFullscreen && element.requestFullscreen()) ||
  479. (element.mozRequestFullScreen && element.mozRequestFullScreen()) ||
  480. (element.webkitRequestFullscreen &&
  481. element.webkitRequestFullscreen()) ||
  482. (element.msRequestFullscreen && element.msRequestFullscreen());
  483. }else {
  484. let elementById = document.getElementById("containerClass");
  485. elementById.style.height = 'calc(100vh - 220px)';
  486. //退出全屏,三目运算符
  487. document.exitFullscreen
  488. ? document.exitFullscreen()
  489. : document.mozCancelFullScreen
  490. ? document.mozCancelFullScreen()
  491. : document.webkitExitFullscreen
  492. ? document.webkitExitFullscreen()
  493. : "";
  494. }
  495. },
  496. handleResave() {
  497. const sheet_name = window.luckysheet.getSheet().name;
  498. const data = window.luckysheet.getSheet(sheet_name);
  499. const workbook_name = window.luckysheet.getWorkbookName();
  500. let empty = this.confirmArrayData(data.data);
  501. if (!empty){
  502. this.$message({
  503. type: "error",
  504. message: '文档内容为空',
  505. });
  506. return;
  507. }
  508. if('请输入标题'== workbook_name || !workbook_name){
  509. this.$message({
  510. type: "error",
  511. message: '请输入标题',
  512. });
  513. return;
  514. }
  515. let value = {
  516. // templateId: this.id,
  517. templateContent: JSON.stringify(data), //文件内容
  518. templateName: workbook_name, //模板名称
  519. templateUrl: "", //文件链接
  520. state: this.state,
  521. mkdirId: this.mkdirId
  522. };
  523. if("edit" ==this.type){
  524. value.id=this.id;
  525. }
  526. this.$http({
  527. url: "/market/workLists/saveOrUpdate",
  528. method: "post",
  529. headers: {
  530. "Content-Type": "application/json",
  531. },
  532. data: value,
  533. }).then((res) => {
  534. console.log("----res",res);
  535. if(res.data.result==0){
  536. this.$message({
  537. type: "success",
  538. message: "保存成功",
  539. });
  540. }else{
  541. this.$message({
  542. type: "error",
  543. message: res.data.body,
  544. });
  545. }
  546. if (this.fullscreen){
  547. this.handleFullscreenOption()
  548. this.$emit("handleFullscreen", false)
  549. }
  550. this.$emit("save");
  551. });
  552. },
  553. },
  554. mounted() {
  555. this.handleInit();
  556. // this.handleChargeList();
  557. },
  558. destroyed() {
  559. window.luckysheet.destroy();
  560. },
  561. };
  562. </script>
  563. <style lang="scss" scope>
  564. .sheet-container {
  565. position: relative;
  566. width: 100%;
  567. height: 100%;
  568. &-block {
  569. overflow: hidden;
  570. position: absolute;
  571. width: 100%;
  572. height: 85%;
  573. }
  574. &-require {
  575. color: red;
  576. }
  577. .el-input {
  578. width: 200px;
  579. margin-right: 10px;
  580. }
  581. }
  582. .form {
  583. &-input {
  584. margin-top: 5px;
  585. .el-input {
  586. width: 150px;
  587. .el-input__inner {
  588. height: 30px !important;
  589. line-height: 30px !important;
  590. }
  591. }
  592. }
  593. &-content {
  594. margin: 0px 10px;
  595. }
  596. //&-select {
  597. // .el-input {
  598. // width: 100px;
  599. // .el-input__inner {
  600. // height: 30px !important;
  601. // line-height: 30px !important;
  602. // }
  603. // }
  604. //}
  605. }
  606. .containerClass{
  607. background: #fff;
  608. border-radius: 5px;
  609. height: calc(100vh - 220px);
  610. width: calc(100% - 6px);
  611. float: left;
  612. display: inline-block;
  613. overflow: hidden;
  614. }
  615. .sheet-container-block_class{
  616. height: calc(100% - 96px);
  617. width: 100%;
  618. }
  619. .containerClass #luckysheet .luckysheet .fa{
  620. font:normal normal normal 14px/1 FontAwesome !important;
  621. }
  622. </style>
  623. <style lang="scss">
  624. body #luckysheet-modal-dialog-slider-pivot .fa{
  625. font:normal normal normal 14px/1 FontAwesome !important;
  626. }
  627. </style>