sheet.vue 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766
  1. <!--
  2. * @Author : yuanrunwei
  3. * @Date : 2021-12-04 14:23:58
  4. * @LastEditors: Please set LastEditors
  5. * @LastEditTime: 2022-01-10 20:43:30
  6. * @FilePath : \spfm-market-front\src\pages\main\performance\components\sheet.vue
  7. -->
  8. <template>
  9. <div class="sheet-container">
  10. <div class="flex-justify-align-end margin-bottom-20">
  11. <el-button
  12. type="primary"
  13. @click="handleVisible"
  14. v-if="['template'].includes(attribute)"
  15. >权限设置</el-button
  16. >
  17. <el-button type="primary" @click="handleDownload">导出</el-button>
  18. <el-button type="primary" @click="handleFullscreen()">全屏显示</el-button>
  19. <template v-if="['edit'].includes(type)">
  20. <el-upload
  21. v-if="!id"
  22. class="margin-right-10 margin-left-10"
  23. action
  24. :on-change="handleChange"
  25. :show-file-list="false"
  26. >
  27. <el-button type="primary">上传</el-button>
  28. </el-upload>
  29. <el-button
  30. v-if="addFlag === '0'"
  31. type="primary"
  32. @click="handleSave"
  33. :disabled="handleForbid()"
  34. ><span>{{ id ? "提交" : "新增" }}</span
  35. ><span>{{
  36. handleForbid() ? `(请先设置权限)` : ""
  37. }}</span></el-button
  38. >
  39. </template>
  40. </div>
  41. <div id="luckysheet" class="sheet-container-block"></div>
  42. <simple-dialog
  43. title="权限设置"
  44. :visible="visible"
  45. :modal="false"
  46. width="1400px"
  47. @confirm="handleAuth"
  48. @cancel="handleVisible"
  49. >
  50. <el-form ref="form" :model="form" label-width="80px">
  51. <el-radio-group v-model="form.permission_type">
  52. <el-form-item>
  53. <el-radio :label="0"><span>无特殊权限</span></el-radio>
  54. <div>
  55. <span class="form-content">负责人</span>
  56. <el-select
  57. v-model="form.person"
  58. multiple
  59. placeholder="请选择负责人"
  60. >
  61. <el-option
  62. v-for="({ label, value }, index) in charge_list"
  63. :key="index"
  64. :label="label"
  65. :value="value"
  66. ></el-option>
  67. </el-select>
  68. </div>
  69. <!-- <div class="form-input">
  70. <span class="form-content"> 可编辑行:从</span>
  71. <el-input v-model="form.col_start" />
  72. <span class="form-content">到</span
  73. ><el-input v-model="form.col_end" />
  74. </div>
  75. <div class="form-input">
  76. <span class="form-content">可编辑列:从</span>
  77. <el-input v-model="form.row_start" />
  78. <span class="form-content">到</span>
  79. <el-input v-model="form.row_end" />
  80. </div> -->
  81. </el-form-item>
  82. <el-form-item>
  83. <el-radio :label="1"><span>特殊权限:</span></el-radio>
  84. <el-form-item
  85. label="负责人"
  86. prop="charge"
  87. v-for="(item, index) in form.charge"
  88. :key="index"
  89. :rules="{
  90. required: true,
  91. message: '负责人不能为空',
  92. trigger: 'blur',
  93. }"
  94. >
  95. <div class="flex">
  96. <el-select
  97. class="margin-bottom-20 margin-right-10"
  98. placeholder="请选择负责人"
  99. v-model="item.person"
  100. filterable
  101. >
  102. <el-option
  103. v-for="({ label, value }, index) in charge_list"
  104. :key="index"
  105. :label="label"
  106. :value="value"
  107. ></el-option>
  108. </el-select>
  109. <div class="form-select">
  110. <span class="form-content">可编辑行:从</span>
  111. <el-input v-model="item.col_start" />
  112. <span class="form-content">到</span>
  113. <el-input v-model="item.col_end" />
  114. </div>
  115. <div class="form-select">
  116. <span class="form-content">可编辑列:从</span>
  117. <el-input v-model="item.row_start" />
  118. <span class="form-content">到</span>
  119. <el-input v-model="item.row_end" />
  120. </div>
  121. </div>
  122. </el-form-item>
  123. <div>
  124. <el-button @click.prevent="handleCharge('add')">添加</el-button>
  125. <el-button
  126. v-if="form.charge.length - 1"
  127. @click.prevent="handleCharge('delete')"
  128. >删除</el-button
  129. >
  130. </div>
  131. </el-form-item>
  132. </el-radio-group>
  133. <!-- <el-form-item
  134. label="可编辑列"
  135. prop="array"
  136. ><el-select
  137. v-model="form.array"
  138. placeholder="可编辑列"
  139. multiple
  140. >
  141. <el-option
  142. v-for="(value, index) in 10"
  143. :key="index"
  144. :label="index + 1"
  145. :value="index + 1"
  146. >
  147. </el-option> </el-select
  148. ></el-form-item>
  149. <el-form-item
  150. label="权限规则"
  151. prop="type"
  152. :rules="{
  153. required: true,
  154. message: '权限规则不能为空',
  155. trigger: 'change',
  156. }"
  157. >
  158. <el-select v-model="form.type">
  159. <el-option
  160. v-for="item in type_options"
  161. :key="item.value"
  162. :label="item.label"
  163. :value="item.value"
  164. ></el-option> </el-select
  165. ></el-form-item>
  166. <el-form-item
  167. label="负责人"
  168. prop="charge"
  169. :rules="{
  170. required: true,
  171. message: '负责人不能为空',
  172. trigger: 'blur',
  173. }"
  174. >
  175. <div
  176. class="flex-justify-start"
  177. v-for="(item, index) in form.charge"
  178. :key="index"
  179. >
  180. <el-select
  181. v-model="item.key"
  182. class="margin-bottom-20 margin-right-10 flex-1"
  183. placeholder="请选择指定列/行"
  184. multiple
  185. >
  186. <el-option
  187. v-for="(value, index) in 10"
  188. :key="index"
  189. :label="index + 1"
  190. :value="index + 1"
  191. >
  192. </el-option>
  193. </el-select>
  194. <el-select
  195. class="margin-bottom-20"
  196. placeholder="请选择负责人"
  197. v-model="item.value"
  198. filterable
  199. >
  200. <el-option
  201. v-for="({ label, value }, index) in charge_list"
  202. :key="index"
  203. :label="label"
  204. :value="value"
  205. ></el-option>
  206. </el-select>
  207. </div>
  208. <div>
  209. <el-button @click.prevent="handleCharge('add')"
  210. >添加</el-button
  211. >
  212. <el-button
  213. v-if="form.charge.length - 1"
  214. @click.prevent="handleCharge('delete')"
  215. >删除</el-button
  216. >
  217. </div>
  218. </el-form-item> -->
  219. </el-form>
  220. <template v-if="id" v-slot:footer><div></div></template>
  221. </simple-dialog>
  222. </div>
  223. </template>
  224. <script>
  225. import luckyexcel from "luckyexcel";
  226. import { exportExcel } from "../common/export";
  227. import simpleDialog from "./dialog.vue";
  228. export default {
  229. components: {
  230. simpleDialog,
  231. },
  232. props: {
  233. type: {
  234. type: String,
  235. default: "view", // view 查看 edit 编辑
  236. },
  237. attribute: {
  238. type: String,
  239. default: "template", // template 模板 order 工单 file 文件
  240. },
  241. id: {
  242. default: null,
  243. },
  244. },
  245. data() {
  246. return {
  247. form: {
  248. charge: [
  249. {
  250. person: [],
  251. col_start: "",
  252. col_end: "",
  253. row_start: "",
  254. row_end: "",
  255. },
  256. ],
  257. array: [],
  258. type: null,
  259. permission_type: null,
  260. col_start: "",
  261. col_end: "",
  262. row_start: "",
  263. row_end: "",
  264. },
  265. // 可提交标志
  266. addFlag: null,
  267. isDisable: true,
  268. issued_id: null,
  269. template_id: null,
  270. visible: false,
  271. row_list: [],
  272. column_list: [],
  273. charge_list: [],
  274. type_options: [
  275. {
  276. value: 1,
  277. label: "按行",
  278. },
  279. // {
  280. // value: 2,
  281. // label: "按列",
  282. // },
  283. ],
  284. };
  285. },
  286. methods: {
  287. handleInit() {
  288. if (this.id) {
  289. this.handleQuery();
  290. } else {
  291. this.handleCreate();
  292. }
  293. },
  294. // // 权限选择
  295. // handleRadio(e){
  296. // console.log(e,'e');
  297. // },
  298. handleAllow({ row, column }) {
  299. return (
  300. (!this.form.permission_type && this.type === "edit") ||
  301. (this.row_list.includes(row) && this.column_list.includes(column))
  302. );
  303. },
  304. async handleQuery() {
  305. let url = "";
  306. let key = "";
  307. switch (this.attribute) {
  308. case "template":
  309. url = "/market/CMKFileTemplate/QueryCMKFileTemplateById";
  310. key = "templateId";
  311. break;
  312. case "order":
  313. url = "/market/CMKIssued/CMKQueryIssuedById";
  314. key = "id";
  315. break;
  316. case "file":
  317. url = "/market/CMKIssued/CMKIssuedProcessByUser";
  318. key = "id";
  319. break;
  320. }
  321. const {
  322. data: {
  323. templateContent,
  324. templateName,
  325. issuedId,
  326. templateId,
  327. list,
  328. addFlag,
  329. },
  330. } = await this.$http({
  331. url,
  332. method: "post",
  333. headers: {
  334. "Content-Type": "application/json",
  335. },
  336. data: {
  337. [key]: this.id,
  338. },
  339. });
  340. this.template_id = templateId;
  341. this.issued_id = issuedId;
  342. this.addFlag = addFlag;
  343. console.log(addFlag, "addFlag");
  344. if (list && list.length) {
  345. const { type } = list[0];
  346. if (type === "1") {
  347. // 公共权限
  348. // const { allowEditingColumns, rowNum } = list[0];
  349. this.form = {
  350. permission_type: Number(type) - 1,
  351. person: list.map((el) => {
  352. return `${el.principalId},${el.principalName}`;
  353. }),
  354. charge: [
  355. {
  356. person: "",
  357. col_start: "",
  358. col_end: "",
  359. row_start: "",
  360. row_end: "",
  361. },
  362. ],
  363. };
  364. } else {
  365. // 特殊权限
  366. this.form = {
  367. permission_type: Number(type) - 1,
  368. col_start: "",
  369. col_end: "",
  370. row_start: "",
  371. row_end: "",
  372. charge: list.map((el) => ({
  373. person: el.principalId + "," + el.principalName,
  374. col_start: el.allowEditingColumns.split(",")[0],
  375. col_end:
  376. el.allowEditingColumns.split(",")[
  377. el.allowEditingColumns.split(",").length - 1
  378. ],
  379. row_start: el.rowNum.split(",")[0],
  380. row_end: el.rowNum.split(",")[el.rowNum.split(",").length - 1],
  381. })),
  382. };
  383. }
  384. // this.form = {
  385. // ...this.form,
  386. // type: type,
  387. // array: allowEditingColumns ? allowEditingColumns.split(",") : [],
  388. // charge: list.map(({ principalId, principalName, rowNum }) => ({
  389. // value: `${principalId},${principalName}`,
  390. // key: rowNum.split(","),
  391. // })),
  392. // };
  393. // this.form = {};
  394. this.row_list =
  395. this.type === "edit" && list[0].rowNum
  396. ? list[0].rowNum
  397. .split(",")
  398. .map((element) => JSON.parse(element) - 1)
  399. : [];
  400. this.column_list =
  401. this.type === "edit" && list[0].allowEditingColumns
  402. ? list[0].allowEditingColumns
  403. .split(",")
  404. .map((element) => JSON.parse(element) - 1)
  405. : [];
  406. }
  407. this.handleCreate({
  408. json: templateContent ? JSON.parse(templateContent) : {},
  409. name: templateName,
  410. type: "json",
  411. });
  412. },
  413. handleForbid() {
  414. // const object = {};
  415. const { permission_type } = this.form;
  416. if (permission_type === 0) {
  417. // 公共权限 暂时不用可编辑行和列
  418. const { person } = this.form;
  419. if (person.length) {
  420. return false;
  421. }
  422. return true;
  423. } else if (permission_type === 1) {
  424. // 特殊权限
  425. let flag = 1;
  426. const { charge } = this.form;
  427. charge.forEach((el) => {
  428. if (
  429. Object.values(el).filter((v) => {
  430. return v !== "";
  431. }).length === 5
  432. ) {
  433. flag = flag * 1;
  434. } else {
  435. flag = flag * 0;
  436. }
  437. });
  438. return !flag;
  439. } else {
  440. return true;
  441. }
  442. // form: {
  443. // charge: [
  444. // {
  445. // person: "",
  446. // col_start: "",
  447. // col_End: "",
  448. // row_start: "",
  449. // row_end: "",
  450. // },
  451. // ],
  452. // array: [],
  453. // type: null,
  454. // permission_type: 0,
  455. // col_start: "",
  456. // col_end: "",
  457. // row_start: "",
  458. // row_end: "",
  459. // },
  460. // charge.map(({ key }) => {
  461. // console.log(key);
  462. // // if (key && value) {
  463. // // object[key] = value;
  464. // // }
  465. // });
  466. // return !(Object.keys(object).length && type);
  467. },
  468. async handleCreate({ file, json, type, name } = {}) {
  469. let that = this;
  470. const options = {
  471. container: "luckysheet",
  472. lang: "zh",
  473. showsheetbar: false,
  474. hook: {
  475. cellEditBefore: function ([
  476. { row_focus: row, column_focus: column },
  477. ]) {
  478. if (!that.handleAllow({ row, column })) {
  479. that.$message.error("您没有编辑权限");
  480. }
  481. },
  482. cellUpdateBefore: function (row, column) {
  483. if (!that.handleAllow({ row, column })) {
  484. return false;
  485. }
  486. },
  487. cellRenderAfter: function (cell, position) {
  488. const { r: row, c: column } = position;
  489. if (cell) {
  490. if (!that.handleAllow({ row, column })) {
  491. cell.bg = "#d5d5d5";
  492. } else {
  493. cell.bg = "#ffffff";
  494. }
  495. }
  496. },
  497. },
  498. };
  499. switch (type) {
  500. case "file":
  501. if (file) {
  502. await new Promise((resolve) => {
  503. luckyexcel.transformExcelToLucky(file, (export_json) => {
  504. options.data = [
  505. ...export_json.sheets.map((element) => ({
  506. ...element,
  507. zoomRatio: 0.75,
  508. })),
  509. ];
  510. options.title = export_json.info.name;
  511. resolve();
  512. });
  513. });
  514. }
  515. break;
  516. case "json":
  517. if (json) {
  518. options.data = [
  519. {
  520. ...json,
  521. zoomRatio: 0.75,
  522. },
  523. ];
  524. options.title = name;
  525. }
  526. break;
  527. }
  528. window.luckysheet.create(options);
  529. let clock = setInterval(() => {
  530. if (window.luckysheet) {
  531. window.luckysheet.refresh();
  532. clearInterval(clock);
  533. }
  534. }, 1000);
  535. },
  536. async handleChange(response) {
  537. this.handleCreate({ file: response.raw, type: "file" });
  538. },
  539. handleDownload() {
  540. exportExcel(
  541. window.luckysheet.getAllSheets(),
  542. window.luckysheet.getWorkbookName()
  543. );
  544. },
  545. async handleAddAuth({ id }) {
  546. // const object = {};
  547. const { permission_type } = this.form;
  548. console.log(id, permission_type);
  549. let reqdata = {
  550. templateId: id,
  551. type: permission_type ? 2 : 1,
  552. };
  553. if (!permission_type) {
  554. // 公共权限
  555. const { person } = this.form;
  556. const principalId = [];
  557. const principalName = [];
  558. person.forEach((el) => {
  559. principalId.push(el.split(",")[0]);
  560. principalName.push(el.split(",")[1]);
  561. });
  562. reqdata.principalId = principalId.join(",");
  563. reqdata.principalName = principalName.join(",");
  564. } else {
  565. const { charge } = this.form;
  566. // 特殊权限
  567. reqdata.specialAuth = charge.map((el) =>
  568. JSON.stringify({
  569. allowEditingColumns: this.paramsArr(el.col_start, el.col_end),
  570. rowNum: this.paramsArr(el.row_start, el.row_end),
  571. principalId: el.person.split(",")[0],
  572. principalName: el.person.split(",")[1],
  573. })
  574. );
  575. }
  576. await this.$http({
  577. url: this.id
  578. ? "/market/CMKFileTemplateAuthority/CMKFileTemplateAuthorityUpdate"
  579. : "/market/CMKFileTemplateAuthority/CMKFileTemplateAuthorityAdd",
  580. method: "post",
  581. headers: {
  582. "Content-Type": "application/json",
  583. },
  584. data: reqdata,
  585. });
  586. this.$message.success("操作成功");
  587. },
  588. async handleSave() {
  589. let edit_url = "";
  590. switch (this.attribute) {
  591. case "template":
  592. edit_url = "";
  593. break;
  594. case "order":
  595. edit_url = "";
  596. break;
  597. case "file":
  598. edit_url = "/market/CMKIssued/CMKIssuedSubmit";
  599. break;
  600. }
  601. const sheet_name = window.luckysheet.getSheet().name;
  602. const data = window.luckysheet.getSheet(sheet_name);
  603. const workbook_name = window.luckysheet.getWorkbookName();
  604. const {
  605. data: { body },
  606. } = await this.$http({
  607. url: this.id
  608. ? edit_url // 编辑
  609. : "/market/CMKFileTemplate/CMKFileTemplateAdd", // 新增
  610. method: "post",
  611. headers: {
  612. "Content-Type": "application/json",
  613. },
  614. data: {
  615. id: this.template_id,
  616. templateContent: JSON.stringify(data),
  617. templateName: workbook_name,
  618. issuedId: this.issued_id,
  619. },
  620. });
  621. // 新增时添加权限
  622. if (!this.id) {
  623. this.handleAddAuth({ id: body });
  624. } else {
  625. this.$message.success("提交成功");
  626. }
  627. this.$emit("save");
  628. },
  629. handleAuth() {
  630. this.$refs["form"].validate((valid) => {
  631. if (valid) {
  632. if (this.handleForbid()) {
  633. this.$message.error("请完善可编辑信息");
  634. return false;
  635. }
  636. this.handleVisible();
  637. if (this.id) {
  638. this.handleAddAuth({ id: this.id });
  639. } else {
  640. this.$message.success("设置成功");
  641. }
  642. }
  643. });
  644. },
  645. // 通用方法用于转化全局
  646. paramsArr(start, end) {
  647. const arr = [];
  648. console.log(start, end);
  649. for (let i = Number(start); i <= Number(end); i++) {
  650. arr.push(i);
  651. }
  652. return arr.join(",");
  653. },
  654. filterName(id, arr) {
  655. return arr.filter((el) => el.secLeaderLogin === id)[0].secLeaderName;
  656. },
  657. handleCharge(type) {
  658. switch (type) {
  659. case "add":
  660. this.form.charge.push({
  661. person: "",
  662. });
  663. this.handleForbid();
  664. break;
  665. case "delete":
  666. this.form.charge.pop();
  667. this.handleForbid();
  668. break;
  669. }
  670. },
  671. handleVisible() {
  672. console.log(this.form, "aada");
  673. this.visible = !this.visible;
  674. },
  675. handleFullscreen() {
  676. const element = document.body;
  677. const is_fullscreen =
  678. document.fullScreen ||
  679. document.mozFullScreen ||
  680. document.webkitIsFullScreen;
  681. if (!is_fullscreen) {
  682. //进入全屏,多重短路表达式
  683. (element.requestFullscreen && element.requestFullscreen()) ||
  684. (element.mozRequestFullScreen && element.mozRequestFullScreen()) ||
  685. (element.webkitRequestFullscreen &&
  686. element.webkitRequestFullscreen()) ||
  687. (element.msRequestFullscreen && element.msRequestFullscreen());
  688. } else {
  689. //退出全屏,三目运算符
  690. document.exitFullscreen
  691. ? document.exitFullscreen()
  692. : document.mozCancelFullScreen
  693. ? document.mozCancelFullScreen()
  694. : document.webkitExitFullscreen
  695. ? document.webkitExitFullscreen()
  696. : "";
  697. }
  698. },
  699. handleChargeList() {
  700. this.$http({
  701. url: "/market/techcentergj/queryLeaderList",
  702. method: "post",
  703. headers: {
  704. "Content-Type": "application/json",
  705. },
  706. data: {},
  707. }).then((response) => {
  708. this.charge_list = response.data.map((element) => ({
  709. label: `${element.ou} ${element.secLeaderName}`,
  710. value: `${element.secLeaderLogin},${element.secLeaderName}`,
  711. }));
  712. });
  713. },
  714. },
  715. mounted() {
  716. this.handleInit();
  717. this.handleChargeList();
  718. },
  719. };
  720. </script>
  721. <style lang="scss" scope>
  722. .sheet-container {
  723. position: fixed;
  724. width: calc(100% - 40px);
  725. height: 100%;
  726. &-block {
  727. overflow: hidden;
  728. position: absolute;
  729. width: 100%;
  730. height: 75%;
  731. }
  732. }
  733. .form {
  734. &-input {
  735. margin-top: 5px;
  736. .el-input {
  737. width: 150px;
  738. .el-input__inner {
  739. height: 30px !important;
  740. line-height: 30px !important;
  741. }
  742. }
  743. }
  744. &-content {
  745. margin: 0px 10px;
  746. }
  747. &-select {
  748. .el-input {
  749. width: 100px;
  750. .el-input__inner {
  751. height: 30px !important;
  752. line-height: 30px !important;
  753. }
  754. }
  755. }
  756. }
  757. </style>