form-component.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505
  1. 'use strict';
  2. function _toConsumableArray(arr) {
  3. if (Array.isArray(arr)) {
  4. for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) {
  5. arr2[i] = arr[i];
  6. }
  7. return arr2;
  8. } else {
  9. return Array.from(arr);
  10. }
  11. }
  12. // 查找html元素
  13. function queryElement(el) {
  14. return document.querySelector(el);
  15. }
  16. // 返回模板字符串
  17. function templateHtml(el) {
  18. return queryElement(el).innerHTML;
  19. }
  20. // Radio组件
  21. function createnRadio() {
  22. var Radio = {
  23. template: templateHtml('#radio'),
  24. model: {
  25. prop: 'value',
  26. event: 'click'
  27. },
  28. props: {
  29. label: {
  30. type: [Number, String],
  31. default: ''
  32. },
  33. value: {
  34. type: [Number, String],
  35. default: ''
  36. }
  37. },
  38. computed: {
  39. isChecked: function isChecked() {
  40. return this.value === this.label;
  41. }
  42. },
  43. methods: {
  44. handleClick: function handleClick() {
  45. this.$emit('click', this.label);
  46. }
  47. }
  48. };
  49. return Radio;
  50. }
  51. // Select组件
  52. function createSelect() {
  53. var Select = {
  54. template: templateHtml('#select'),
  55. props: {
  56. value: {
  57. type: [Number, String],
  58. default: ''
  59. },
  60. placeholder: {
  61. type: String,
  62. default: ''
  63. }
  64. },
  65. model: {
  66. prop: 'value',
  67. event: 'change'
  68. },
  69. data: function data() {
  70. return {
  71. optionsVisible: false,
  72. label: '',
  73. };
  74. },
  75. watch:{
  76. value(nVal){
  77. const that = this;
  78. this.$children.forEach(function(o){
  79. if(o.value === nVal){
  80. that.label = o.label
  81. }
  82. });
  83. },
  84. },
  85. mounted: function mounted() {
  86. var _this = this;
  87. document.addEventListener('click', function () {
  88. _this.optionsVisible = false;
  89. });
  90. },
  91. beforeDestroy: function beforeDestroy() {
  92. document.removeEventListener('click');
  93. }
  94. };
  95. return Select;
  96. }
  97. // Option组件
  98. function createOption() {
  99. var Option = {
  100. template: templateHtml('#option'),
  101. props: {
  102. label: {
  103. type: [String, Number],
  104. default: ''
  105. },
  106. value: {
  107. type: [String, Number],
  108. default: ''
  109. }
  110. },
  111. methods: {
  112. handleClick: function handleClick() {
  113. this.$parent.$emit('change', this.value);
  114. this.$parent.$data.optionsVisible = false;
  115. // this.$parent.$data.label = this.label;
  116. }
  117. }
  118. };
  119. return Option;
  120. }
  121. // 上传文件组件
  122. function createUploadImage() {
  123. var UploadImage = {
  124. template: templateHtml('#imageUpload'),
  125. props: {
  126. placeholder: {
  127. type: String,
  128. default: '上传图片'
  129. },
  130. multiple: {
  131. type: Boolean,
  132. default: false
  133. },
  134. limit: {
  135. type: Number,
  136. default: 9
  137. },
  138. imgList: {
  139. type: Array,
  140. default: function _default() {
  141. return [];
  142. }
  143. }
  144. },
  145. data: function data() {
  146. return {
  147. files: [],
  148. accept: '.jpg, .jpeg, .png, .gif',
  149. };
  150. },
  151. created: function created() {
  152. // 初始化列表
  153. this.initImagelist(this.imgList);
  154. },
  155. computed: {
  156. // 当前选中的图片数量
  157. fileCount: function fileCount() {
  158. return this.files.length;
  159. },
  160. // 是否能选择图片
  161. canChooseImage: function canChooseImage() {
  162. return (this.multiple && this.fileCount < this.limit) || (!this.multiple && this.fileCount === 0);
  163. }
  164. },
  165. watch: {
  166. imgList: function(nVal){
  167. this.initImagelist(nVal)
  168. }
  169. },
  170. methods: {
  171. // 初始化图片列表
  172. initImagelist: function initImagelist(fileList = []){
  173. if(fileList.length <=0) return;
  174. this.files = [];
  175. if(this.multiple){
  176. this.files = fileList.slice(0, this.limit);
  177. }else{
  178. this.files.push(fileList[0]);
  179. }
  180. },
  181. // 点击事件
  182. handleClick: function handleClick() {
  183. this.$refs.file.click();
  184. },
  185. // 选择图片
  186. handleChooseImage: function handleChooseImage(e) {
  187. var that = this;
  188. var files = [].concat(_toConsumableArray(e.target.files));
  189. e.target.value = '';
  190. // 如果能选取图片
  191. if(!this.canChooseImage) return;
  192. // 取合适数量的图片
  193. files = this.handleFilterImage(files);
  194. // 图片本地预览链接
  195. files.forEach(function(file){
  196. file.url = URL.createObjectURL(file);
  197. that.files.push(file);
  198. });
  199. this.$emit('change', this.files);
  200. },
  201. // 筛选图片 单张 || limit张
  202. handleFilterImage: function handleFilterImage(files) {
  203. if(files.length <= 0) return [];
  204. if(this.multiple){
  205. console.log(this.limit - this.fileCount);
  206. // 多选
  207. files = files.slice(0, this.limit - this.fileCount)
  208. }else{
  209. // 单选
  210. files = files.slice(0, 1)
  211. }
  212. return files
  213. },
  214. // 删除图片
  215. removeImage: function removeImage(file, index) {
  216. this.files.splice(index, 1);
  217. this.$emit('remove', index);
  218. }
  219. }
  220. };
  221. return UploadImage;
  222. }
  223. //富文本框封装
  224. function createEditorComponent() {
  225. window.editorCount = 0;
  226. const Editor = {
  227. render: function render(h){
  228. return h('div', { class: { 'cm': true, 'editor': true }, attrs: { id: this.editorId } })
  229. },
  230. model: {
  231. prop: 'value',
  232. event: 'change'
  233. },
  234. props:{
  235. value: {
  236. type: String,
  237. default: ''
  238. },
  239. placeholder:{
  240. type: String,
  241. default: ''
  242. },
  243. text: {
  244. type: String,
  245. default: ''
  246. }
  247. },
  248. data() {
  249. return {
  250. editorId: '',
  251. editor: null
  252. }
  253. },
  254. watch:{
  255. text(nVal){
  256. if(!this.editor) return;
  257. this.editor.txt.html(this.value) // 重新设置编辑器内容
  258. }
  259. },
  260. created: function created() {
  261. window.editorCount++;
  262. this.editorId = 'editorId-' + window.editorCount;
  263. },
  264. mounted: function mounted() {
  265. this.createEditor();
  266. },
  267. beforeDestroy: function beforeDestroy(){
  268. this.editor.destroy();
  269. this.editor = null;
  270. },
  271. methods: {
  272. // 创建编辑器
  273. createEditor: function createEditor() {
  274. const E = window.wangEditor;
  275. this.editor = new E('#' + this.editorId);
  276. // 或者 const editor = new E( document.getElementById('div1') )
  277. this.initEditorOptions();
  278. this.editor.create();
  279. },
  280. // 富文本框配置
  281. initEditorOptions: function initEditorOptions() {
  282. this.editor.config.zIndex = 333;
  283. this.editor.config.height = 200;
  284. this.editor.config.uploadImgMaxSize = 2 * 1024 * 1024;
  285. this.editor.config.uploadImgMaxLength = 5; // 一次最多上传 5 个图片
  286. this.editor.config.placeholder = this.placeholder;
  287. var that = this;
  288. this.editor.config.onchange = function (newHtml) {
  289. that.$emit('change', newHtml)
  290. };
  291. this.editor.config.customUploadImg = function (resultFiles, insertImgFn) {
  292. resultFiles.forEach(function (file) {
  293. // resultFiles 是 input 中选中的文件列表
  294. // insertImgFn 是获取图片 url 后,插入到编辑器的方法
  295. that.uploadImage(file).then(function (res) {
  296. insertImgFn(res);
  297. });
  298. });
  299. };
  300. },
  301. // 上传图片
  302. uploadImage: function uploadImage(file) {
  303. var formData = new FormData();
  304. formData.append('file', file);
  305. return new Promise(function (resolve, reject) {
  306. PublicApi.uploadimg(formData, function (res) {
  307. if (res.code === 0) {
  308. resolve(res.data);
  309. }
  310. reject();
  311. });
  312. });
  313. }
  314. }
  315. };
  316. return Editor;
  317. }
  318. // 文本框列表
  319. function createInputGroup() {
  320. const InputGroup = {
  321. template: templateHtml('#inputGroup'),
  322. props:{
  323. // 最小数量
  324. minLimit: {
  325. type: Number,
  326. default: 5
  327. },
  328. // 回显列表
  329. list: {
  330. type: Array,
  331. default: function _default() {
  332. return [];
  333. }
  334. },
  335. placeholderList: {
  336. type: Array,
  337. default: function _default() {
  338. return [];
  339. }
  340. },
  341. keyMap: {
  342. type: Object,
  343. default: () => ({
  344. key: 'name',
  345. value: 'value'
  346. })
  347. },
  348. addText:{
  349. type: String,
  350. default: ''
  351. }
  352. },
  353. data: function(){
  354. return {
  355. dataList: [],
  356. placeholder: { label: '参数名',value: '请输入参数信息'},
  357. }
  358. },
  359. computed:{
  360. showList: function(){
  361. const len = this.dataList.length;
  362. if(len >= this.minLimit) return this.dataList;
  363. const emptyList = this.setEmptyData(this.minLimit - len);
  364. return this.dataList.concat(emptyList);
  365. }
  366. },
  367. created: function(){
  368. this.dataList = this.list;
  369. },
  370. watch:{
  371. list: function(nVal){
  372. this.dataList = nVal;
  373. }
  374. },
  375. methods:{
  376. // add
  377. getPlaceholder(index){
  378. if(this.placeholderList.length <= 0) return this.placeholder;
  379. return this.placeholderList[index] || this.placeholder;
  380. },
  381. //添加空数据
  382. setEmptyData(size) {
  383. const list = [];
  384. for (let i = 0; i < size; i++) {
  385. let obj = Object.create(null);
  386. obj[this.keyMap.key] = "";
  387. obj[this.keyMap.value] = '';
  388. list.push(obj)
  389. }
  390. return list
  391. },
  392. handleRemove(item, index){
  393. this.$emit('remove', { item, index});
  394. },
  395. handleAddOnce(){
  396. this.$emit('add')
  397. }
  398. }
  399. };
  400. return InputGroup;
  401. }
  402. // 问答组件
  403. function createQuestionGroup(){
  404. const QuestionGroup = {
  405. template: templateHtml('#questionGroup'),
  406. props:{
  407. // 最小数量
  408. minLimit: {
  409. type: Number,
  410. default: 5
  411. },
  412. // 回显列表
  413. list: {
  414. type: Array,
  415. default: function _default() {
  416. return [];
  417. }
  418. },
  419. placeholderList: {
  420. type: Array,
  421. default: function _default() {
  422. return [];
  423. }
  424. },
  425. keyMap: {
  426. type: Object,
  427. default: () => ({
  428. key: 'name',
  429. value: 'value'
  430. })
  431. },
  432. addText:{
  433. type: String,
  434. default: ''
  435. }
  436. },
  437. data: function(){
  438. return {
  439. dataList: [],
  440. placeholder: { label: '请输入问题',value: '请输入回答'},
  441. }
  442. },
  443. computed:{
  444. showList: function(){
  445. const len = this.dataList.length;
  446. if(len >= this.minLimit) return this.dataList;
  447. const emptyList = this.setEmptyData(this.minLimit - len);
  448. return this.dataList.concat(emptyList);
  449. }
  450. },
  451. created: function(){
  452. this.dataList = this.list;
  453. },
  454. watch:{
  455. list: function(nVal){
  456. this.dataList = nVal;
  457. }
  458. },
  459. methods:{
  460. // add
  461. getPlaceholder(index){
  462. if(this.placeholderList.length <= 0) return this.placeholder;
  463. return this.placeholderList[index] || this.placeholder;
  464. },
  465. //添加空数据
  466. setEmptyData(size) {
  467. const list = [];
  468. for (let i = 0; i < size; i++) {
  469. let obj = Object.create(null);
  470. obj[this.keyMap.key] = "";
  471. obj[this.keyMap.value] = '';
  472. list.push(obj)
  473. }
  474. return list
  475. },
  476. handleRemove(item){
  477. this.$emit('remove', item);
  478. },
  479. handleAddOnce(){
  480. this.$emit('add')
  481. }
  482. }
  483. };
  484. return QuestionGroup;
  485. }