sheet.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427
  1. <!--
  2. * @Author : yuanrunwei
  3. * @Date : 2021-12-04 14:23:58
  4. * @LastEditors : yuanrunwei
  5. * @LastEditTime : 2021-12-24 10:05:55
  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 type="primary" @click="handleVisible"
  12. >权限设置</el-button
  13. >
  14. <el-button type="primary" @click="handleDownload">导出</el-button>
  15. <el-button type="primary" @click="handleFullscreen()"
  16. >全屏显示</el-button
  17. >
  18. <template v-if="type === 'edit'">
  19. <el-upload
  20. class="margin-right-10 margin-left-10"
  21. action
  22. :on-change="handleChange"
  23. :show-file-list="false"
  24. >
  25. <el-button type="primary">上传</el-button>
  26. </el-upload>
  27. <el-button
  28. type="primary"
  29. @click="handleSave"
  30. :disabled="handleForbid()"
  31. >保存</el-button
  32. >
  33. </template>
  34. </div>
  35. <div id="luckysheet" class="sheet-container-block"></div>
  36. <simple-dialog
  37. title="权限设置"
  38. :visible="visible"
  39. :modal="false"
  40. width="700px"
  41. @confirm="handlePower"
  42. @cancel="handleVisible"
  43. >
  44. <el-form ref="form" :model="form" label-width="100px">
  45. <el-form-item
  46. label="可编辑列"
  47. prop="array"
  48. :rules="{
  49. required: true,
  50. message: '可编辑列不能为空',
  51. trigger: 'change',
  52. }"
  53. ><el-select
  54. v-model="form.array"
  55. placeholder="可编辑列"
  56. multiple
  57. >
  58. <el-option
  59. v-for="(value, index) in 10"
  60. :key="index"
  61. :label="index"
  62. :value="index"
  63. >
  64. </el-option> </el-select
  65. ></el-form-item>
  66. <el-form-item
  67. label="权限规则"
  68. prop="type"
  69. :rules="{
  70. required: true,
  71. message: '权限规则不能为空',
  72. trigger: 'change',
  73. }"
  74. >
  75. <el-select v-model="form.type">
  76. <el-option
  77. v-for="item in type_options"
  78. :key="item.value"
  79. :label="item.label"
  80. :value="item.value"
  81. ></el-option> </el-select
  82. ></el-form-item>
  83. <el-form-item
  84. label="负责人"
  85. prop="charge"
  86. :rules="{
  87. required: true,
  88. message: '负责人不能为空',
  89. trigger: 'blur',
  90. }"
  91. >
  92. <div
  93. class="flex-justify-start"
  94. v-for="(item, index) in form.charge"
  95. :key="index"
  96. >
  97. <el-select
  98. v-model="item.key"
  99. class="margin-bottom-20 margin-right-10 flex-1"
  100. placeholder="请选择指定列/行"
  101. multiple
  102. >
  103. <el-option
  104. v-for="(value, index) in 10"
  105. :key="index"
  106. :label="index"
  107. :value="index"
  108. >
  109. </el-option>
  110. </el-select>
  111. <el-select
  112. class="margin-bottom-20"
  113. placeholder="请选择负责人"
  114. v-model="item.value"
  115. filterable
  116. >
  117. <el-option
  118. v-for="({ label, value }, index) in charge_list"
  119. :key="index"
  120. :label="label"
  121. :value="value"
  122. ></el-option>
  123. </el-select>
  124. </div>
  125. <div>
  126. <el-button @click.prevent="handleCharge('add')"
  127. >添加</el-button
  128. >
  129. <el-button
  130. v-if="form.charge.length - 1"
  131. @click.prevent="handleCharge('delete')"
  132. >删除</el-button
  133. >
  134. </div>
  135. </el-form-item>
  136. </el-form>
  137. </simple-dialog>
  138. </div>
  139. </template>
  140. <script>
  141. import luckyexcel from "luckyexcel";
  142. import { exportExcel } from "../common/export";
  143. import simpleDialog from "./dialog.vue";
  144. export default {
  145. components: {
  146. simpleDialog,
  147. },
  148. props: {
  149. type: {
  150. type: String,
  151. default: "view",
  152. },
  153. id: {
  154. type: Number,
  155. default: null,
  156. },
  157. },
  158. data() {
  159. return {
  160. form: {
  161. charge: [{ value: "" }],
  162. },
  163. visible: false,
  164. row_list: [],
  165. column_list: [],
  166. charge_list: [],
  167. type_options: [
  168. {
  169. value: 1,
  170. label: "按行",
  171. },
  172. {
  173. value: 2,
  174. label: "按列",
  175. },
  176. ],
  177. };
  178. },
  179. methods: {
  180. handleInit() {
  181. if (this.id) {
  182. this.handleQuery();
  183. } else {
  184. this.handleCreate();
  185. }
  186. },
  187. handleAllow({ row, column }) {
  188. return (
  189. this.row_list.includes(row) && this.column_list.includes(column)
  190. );
  191. },
  192. async handleQuery() {
  193. const {
  194. data: { templateContent, templateName },
  195. } = await this.$http({
  196. url: "/market/CMKFileTemplate/QueryCMKFileTemplateById",
  197. method: "post",
  198. headers: {
  199. "Content-Type": "application/json",
  200. },
  201. data: {
  202. templateId: this.id,
  203. },
  204. });
  205. this.handleCreate({
  206. json: JSON.parse(templateContent),
  207. name: templateName,
  208. type: "json",
  209. });
  210. },
  211. handleForbid() {
  212. const object = {};
  213. const { array, type, charge } = this.form;
  214. charge.map(({ key, value }) => {
  215. if (key && value) {
  216. object[key] = value;
  217. }
  218. });
  219. return !(Object.keys(object).length && array.length && type);
  220. },
  221. async handleCreate({ file, json, type, name } = {}) {
  222. let that = this;
  223. const options = {
  224. container: "luckysheet",
  225. lang: "zh",
  226. showsheetbar: false,
  227. hook: {
  228. cellEditBefore: function ([
  229. { row_focus: row, column_focus: column },
  230. ]) {
  231. if (!that.handleAllow({ row, column })) {
  232. that.$message.error("您没有编辑权限");
  233. }
  234. },
  235. cellUpdateBefore: function (row, column) {
  236. if (!that.handleAllow({ row, column })) {
  237. return false;
  238. }
  239. },
  240. cellRenderAfter: function (cell, position) {
  241. const { r: row, c: column } = position;
  242. if (!that.handleAllow({ row, column })) {
  243. if (cell) {
  244. cell.bg = "#d5d5d5";
  245. }
  246. }
  247. },
  248. },
  249. };
  250. switch (type) {
  251. case "file":
  252. if (file) {
  253. await new Promise((resolve) => {
  254. luckyexcel.transformExcelToLucky(
  255. file,
  256. (export_json) => {
  257. options.data = [
  258. ...export_json.sheets.map(
  259. (element) => ({
  260. ...element,
  261. zoomRatio: 0.75,
  262. })
  263. ),
  264. ];
  265. options.title = export_json.info.name;
  266. resolve();
  267. }
  268. );
  269. });
  270. }
  271. break;
  272. case "json":
  273. if (json) {
  274. options.data = [
  275. {
  276. ...json,
  277. zoomRatio: 0.75,
  278. },
  279. ];
  280. options.title = name;
  281. }
  282. break;
  283. }
  284. window.luckysheet.create(options);
  285. },
  286. async handleChange(response) {
  287. this.handleCreate({ file: response.raw, type: "file" });
  288. },
  289. handleDownload() {
  290. exportExcel(
  291. window.luckysheet.getAllSheets(),
  292. window.luckysheet.getWorkbookName()
  293. );
  294. },
  295. async handleSave() {
  296. const sheet_name = window.luckysheet.getSheet().name;
  297. const data = window.luckysheet.getSheet(sheet_name);
  298. const workbook_name = window.luckysheet.getWorkbookName();
  299. const {
  300. data: { body },
  301. } = await this.$http({
  302. url: "/market/CMKFileTemplate/CMKFileTemplateAdd",
  303. method: "post",
  304. headers: {
  305. "Content-Type": "application/json",
  306. },
  307. data: {
  308. templateContent: JSON.stringify(data),
  309. templateName: workbook_name,
  310. },
  311. });
  312. const object = {};
  313. const { array, charge, type } = this.form;
  314. charge.map(({ key, value }) => {
  315. if (key && value) {
  316. object[key] = value;
  317. }
  318. });
  319. await this.$http({
  320. url: "/market/CMKFileTemplateAuthority/CMKFileTemplateAuthorityAdd",
  321. method: "post",
  322. headers: {
  323. "Content-Type": "application/json",
  324. },
  325. data: {
  326. allowEditingColumns: array.join(","),
  327. auth: JSON.stringify(object),
  328. templateId: body,
  329. type,
  330. },
  331. });
  332. this.$message.success("保存成功");
  333. },
  334. handlePower() {
  335. this.$refs["form"].validate((valid) => {
  336. if (valid) {
  337. if (this.handleForbid()) {
  338. this.$message.error("请选择负责人编辑权限");
  339. return false;
  340. }
  341. this.handleVisible();
  342. this.$message.success("设置成功");
  343. }
  344. });
  345. },
  346. handleCharge(type) {
  347. switch (type) {
  348. case "add":
  349. this.form.charge.push({
  350. value: "",
  351. });
  352. break;
  353. case "delete":
  354. this.form.charge.pop();
  355. break;
  356. }
  357. },
  358. handleVisible() {
  359. this.visible = !this.visible;
  360. },
  361. handleFullscreen() {
  362. const element = document.body;
  363. const is_fullscreen =
  364. document.fullScreen ||
  365. document.mozFullScreen ||
  366. document.webkitIsFullScreen;
  367. if (!is_fullscreen) {
  368. //进入全屏,多重短路表达式
  369. (element.requestFullscreen && element.requestFullscreen()) ||
  370. (element.mozRequestFullScreen &&
  371. element.mozRequestFullScreen()) ||
  372. (element.webkitRequestFullscreen &&
  373. element.webkitRequestFullscreen()) ||
  374. (element.msRequestFullscreen &&
  375. element.msRequestFullscreen());
  376. } else {
  377. //退出全屏,三目运算符
  378. document.exitFullscreen
  379. ? document.exitFullscreen()
  380. : document.mozCancelFullScreen
  381. ? document.mozCancelFullScreen()
  382. : document.webkitExitFullscreen
  383. ? document.webkitExitFullscreen()
  384. : "";
  385. }
  386. },
  387. handleChargeList() {
  388. this.$http({
  389. url: "/market/techcentergj/queryLeaderList",
  390. method: "post",
  391. headers: {
  392. "Content-Type": "application/json",
  393. },
  394. data: {},
  395. }).then((response) => {
  396. this.charge_list = response.data.map((element) => ({
  397. label: `${element.ou} ${element.secLeaderName}`,
  398. value: `${element.secLeaderLogin},${element.secLeaderName}`,
  399. }));
  400. });
  401. },
  402. },
  403. mounted() {
  404. this.handleInit();
  405. this.handleChargeList();
  406. },
  407. };
  408. </script>
  409. <style lang="scss" scope>
  410. .sheet-container {
  411. position: fixed;
  412. width: calc(100% - 40px);
  413. height: 100%;
  414. &-block {
  415. overflow: hidden;
  416. position: absolute;
  417. width: 100%;
  418. height: 75%;
  419. }
  420. }
  421. </style>