PreviewDialog.vue 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. <template>
  2. <cus-dialog
  3. :visible="previewVisible"
  4. @on-close="previewVisible = false"
  5. ref="widgetPreview"
  6. :title="$t('fm.actions.preview')"
  7. fullscreen
  8. custom-class="fm-generate-preview-container"
  9. :close-on-press-escape="false"
  10. >
  11. <el-radio-group v-model="platform" size="small" class="platform-controller">
  12. <el-radio-button label="pc" value="pc"><i class="fm-iconfont icon-pc"/></el-radio-button>
  13. <el-radio-button label="pad" value="pad"><i class="fm-iconfont icon-pad"/></el-radio-button>
  14. <el-radio-button label="mobile" value="mobile"><i class="fm-iconfont icon-mobile"/></el-radio-button>
  15. </el-radio-group>
  16. <div class="fm-generate-preview" :class="`${platform}`" v-loading="exportLoading || printLoading">
  17. <el-scrollbar>
  18. <template v-if="platform == 'mobile' && previewForm.config.mobileVant">
  19. <vant-generate-form preview :print-read="printRead" :platform="platform" :edit="formEdit" insite="true" v-if="previewVisible" :data="previewForm" :value="widgetModels" ref="generateVantForm">
  20. <template v-slot:blank>
  21. </template>
  22. </vant-generate-form>
  23. </template>
  24. <template v-else>
  25. <generate-form preview :print-read="printRead" :platform="platform" id="export-id" :edit="formEdit" insite="true" v-if="previewVisible && (previewForm.config.ui == 'element' || !previewForm.config.ui)" :data="previewForm" :value="widgetModels" ref="generateForm">
  26. <template v-slot:blank>
  27. </template>
  28. </generate-form>
  29. <template v-if="useAntdForm">
  30. <antd-generate-form preview :print-read="printRead" :platform="platform" :edit="formEdit" insite="true" v-if="previewVisible && previewForm.config.ui == 'antd'" :data="previewForm" :value="widgetModels" ref="generateAntForm">
  31. <template v-slot:blank>
  32. </template>
  33. </antd-generate-form>
  34. </template>
  35. </template>
  36. </el-scrollbar>
  37. <div v-show="platform === 'mobile' && showQrcode" style=" position: absolute; top: 80px; left: 50%; margin-left: 220px;">
  38. <el-card shadow="never" :body-style="{
  39. padding: '15px'
  40. }">
  41. <div style="line-height: 20px; margin-bottom: 10px; ">{{$t('fm.description.qrcodePreview')}}</div>
  42. <div id="fmpreviewqrcode"></div>
  43. </el-card>
  44. </div>
  45. </div>
  46. <template #action>
  47. <el-button size="large" type="primary" @click="handleTest">{{$t('fm.actions.getData')}}</el-button>
  48. <el-button size="large" @click="handleReset">{{$t('fm.actions.reset')}}</el-button>
  49. <el-button size="large" @click="formEdit = false" v-if="formEdit" :disabled="printRead">{{$t('fm.actions.disabledEdit')}}</el-button>
  50. <el-button size="large" @click="formEdit = true" v-else :disabled="printRead">{{$t('fm.actions.enabledEdit')}}</el-button>
  51. <el-button size="large" @click="printRead = true" v-if="!printRead">{{$t('fm.actions.printReadMode')}}</el-button>
  52. <el-button size="large" @click="printRead = false" v-if="printRead">{{$t('fm.actions.editMode')}}</el-button>
  53. <el-button size="large" @click="handlePrint" :loading="printLoading">{{$t('fm.actions.print')}}</el-button>
  54. <el-button size="large" @click="handleExportPDF" :loading="exportLoading">{{$t('fm.actions.exportPDF')}}</el-button>
  55. <el-button size="large" @click="previewVisible = false" type="info" plain>{{$t('fm.actions.close')}}</el-button>
  56. </template>
  57. </cus-dialog>
  58. <PreviewPdf ref="pdfPreview"></PreviewPdf>
  59. </template>
  60. <script>
  61. import CusDialog from './CusDialog.vue'
  62. import GenerateForm from './GenerateForm.vue'
  63. import AntdGenerateForm from './AntdvGenerator/GenerateForm.vue'
  64. import VantGenerateForm from './VantGenerator/GenerateForm.vue'
  65. import { consoleError } from '../util/index'
  66. import { ElMessage } from '../util/message.js'
  67. import PreviewPdf from './PreviewPdf.vue'
  68. import { inject } from 'vue'
  69. export default {
  70. components: {
  71. CusDialog,
  72. GenerateForm,
  73. AntdGenerateForm,
  74. VantGenerateForm,
  75. PreviewPdf
  76. },
  77. props: {
  78. },
  79. inject: {
  80. themeAlgorithm: {
  81. default: null
  82. },
  83. useAntdForm: {
  84. default: false
  85. },
  86. getVantMobile: {
  87. default: false
  88. }
  89. },
  90. emits: ['get-data-success'],
  91. data () {
  92. return {
  93. previewVisible: false,
  94. formEdit: true,
  95. previewForm: {},
  96. widgetModels: {},
  97. platform: 'pc',
  98. printRead: false,
  99. showQrcode: false,
  100. exportLoading: false,
  101. printLoading: false
  102. }
  103. },
  104. methods: {
  105. generateQrcode (url) {
  106. if (!window.QRCode) {
  107. consoleError('QRCode is not defined')
  108. return false
  109. }
  110. setTimeout(() => {
  111. this.showQrcode = true
  112. var qrcode = new QRCode(document.getElementById("fmpreviewqrcode"), {
  113. width : 120,
  114. height : 120
  115. });
  116. qrcode.makeCode(url)
  117. }, 500)
  118. },
  119. preview (data, platform) {
  120. this.previewForm = data
  121. this.formEdit = this.previewVisible = true
  122. this.printRead = false
  123. this.showQrcode = false
  124. this.platform = platform
  125. this.$nextTick(() => {
  126. window.document.getElementsByClassName('fm-generate-preview-container')?.[0].removeAttribute('tabindex')
  127. })
  128. },
  129. getFormRef () {
  130. let $form = null
  131. if (this.$refs.generateForm) {
  132. $form = this.$refs.generateForm
  133. }
  134. if (this.$refs.generateAntForm) {
  135. $form = this.$refs.generateAntForm
  136. }
  137. if (this.$refs.generateVantForm) {
  138. $form = this.$refs.generateVantForm
  139. }
  140. return $form
  141. },
  142. handleTest () {
  143. const $form = this.getFormRef()
  144. $form && $form.getData().then(data => {
  145. this.$emit('get-data-success', data)
  146. this.$refs.widgetPreview.end()
  147. }).catch(e => {
  148. ElMessage({
  149. message: e,
  150. type: 'error'
  151. }, this)
  152. this.$refs.widgetPreview.end()
  153. })
  154. },
  155. handleReset () {
  156. const $form = this.getFormRef()
  157. $form && $form.reset()
  158. },
  159. handleExportWord () {
  160. var rules = "",
  161. ss = document.styleSheets;
  162. for (var i = 0; i < ss.length; ++i) {
  163. for (var x = 0; x < ss[i].cssRules.length; ++x) {
  164. rules += ss[i].cssRules[x].cssText;
  165. }
  166. }
  167. var header = `<html xmlns:o='urn:schemas-microsoft-com:office:office' xmlns:w='urn:schemas-microsoft-com:office:word' xmlns='http://www.w3.org/TR/REC-html40'>
  168. <head><meta charset='utf-8'><title>Export HTML to Word Document with JavaScript</title>
  169. <style>${rules}</style>
  170. </head><body>`;
  171. var footer = "</body></html>";
  172. var html = header+document.getElementById('export-id').innerHTML+footer;
  173. var blob = new Blob(['\ufeff', html], {
  174. type: 'application/msword'
  175. });
  176. // Specify link url
  177. var url = 'data:application/vnd.ms-word;charset=utf-8,' + encodeURIComponent(html);
  178. // Specify file name
  179. let filename = filename?filename+'.doc':'document.doc';
  180. // Create download link element
  181. var downloadLink = document.createElement("a");
  182. document.body.appendChild(downloadLink);
  183. if(navigator.msSaveOrOpenBlob ){
  184. navigator.msSaveOrOpenBlob(blob, filename);
  185. }else{
  186. // Create a link to the file
  187. downloadLink.href = url;
  188. // Setting the file name
  189. downloadLink.download = filename;
  190. //triggering the function
  191. downloadLink.click();
  192. }
  193. document.body.removeChild(downloadLink);
  194. },
  195. handlePrint () {
  196. const tempPrint = this.printRead
  197. this.printLoading = true
  198. setTimeout(() => {
  199. this.printRead = true
  200. this.$nextTick(() => {
  201. const $form = this.getFormRef()
  202. $form && $form.print().then().finally(() => {
  203. this.printLoading = false
  204. this.printRead = tempPrint
  205. })
  206. })
  207. }, 100)
  208. },
  209. handleExportPDF () {
  210. const tempPrint = this.printRead
  211. this.exportLoading = true
  212. setTimeout(() => {
  213. this.printRead = true
  214. this.$nextTick(() => {
  215. const $form = this.getFormRef()
  216. $form && $form.exportPDF().then(data => {
  217. this.$refs.pdfPreview.open(data)
  218. }).finally(() => {
  219. this.exportLoading = false
  220. this.printRead = tempPrint
  221. })
  222. })
  223. }, 100)
  224. }
  225. }
  226. }
  227. </script>
  228. <style lang="scss">
  229. .fm-generate-preview-container{
  230. .platform-controller{
  231. position: absolute;
  232. width: 120px;
  233. top: 50px;
  234. z-index: 5000;
  235. left: 20px;
  236. // margin-left: -60px;
  237. }
  238. .fm-generate-preview{
  239. margin-top: 15px !important;
  240. }
  241. }
  242. @media print{
  243. .fm-design-container{
  244. display: none;
  245. }
  246. .fm-generate-preview-container{
  247. position: relative;
  248. .el-dialog{
  249. display: block;
  250. }
  251. .el-dialog__header{
  252. display: none;
  253. }
  254. .el-dialog__footer{
  255. display: none;
  256. }
  257. .el-dialog__body{
  258. padding: 0;
  259. display: block;
  260. .fm-generate-preview{
  261. box-shadow: none;
  262. border: 0;
  263. }
  264. }
  265. .platform-controller{
  266. display: none;
  267. }
  268. }
  269. }
  270. </style>