Form.js 51 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128
  1. import {formatDate,formatDateTime,formatTime,copyObj,inArray,getfileImage} from '../util.js';
  2. import fieldlist from '../components/Fieldlist.js';
  3. import selectpage from '../components/SelectPage.js';
  4. import attachment from "../components/Attachment.js";
  5. import wangeditor from "../components/editor/Wangeditor.js";
  6. import template from './template/FormTemp.js';
  7. const getParams=function(obj,str) {
  8. const regex = /{([^}]+)}/g;
  9. const matches = str.match(regex);
  10. if (!matches) return str;
  11. matches.forEach(match => {
  12. const key = match.replace('{', '').replace('}', '');
  13. let value = obj[key];
  14. if(value instanceof Array){
  15. value=value.join(',');
  16. }
  17. str = str.replace(match, value);
  18. });
  19. return str;
  20. }
  21. const getValue=function(row,field,defaultValue){
  22. let fieldarr=field.split('.');
  23. for(let i=0;i<fieldarr.length;i++){
  24. row=row[fieldarr[i]];
  25. if(row==undefined){
  26. return defaultValue;
  27. }
  28. }
  29. return row;
  30. }
  31. const changeCheckboxValue=function (searchlist,value){
  32. let r=[];
  33. for(let i=0;i<value.length;i++){
  34. for(let key in searchlist){
  35. if(value[i]==key){
  36. r.push(key);
  37. }
  38. }
  39. }
  40. return r;
  41. }
  42. export default {
  43. name: "YunForm",
  44. components:{'Fieldlist':fieldlist,'SelectPage':selectpage,'Attachment':attachment,'Wangeditor':wangeditor},
  45. data: function () {
  46. return {
  47. isLayer:false,
  48. documentWidth:'',
  49. activeStep:0,
  50. activeTab:0,
  51. form_:{
  52. columns:[],
  53. data:{},
  54. rules:{}
  55. }
  56. }
  57. },
  58. mounted:function(){
  59. this.documentWidth=document.documentElement.clientWidth;
  60. if(top!=window){
  61. let iframe = top.document.querySelector('iframe[src="'+window.location.href+'"][class="layer-iframe"]');
  62. if(iframe){
  63. this.isLayer=true;
  64. }
  65. }
  66. this.reset();
  67. },
  68. props:{
  69. data:{
  70. type:Object,
  71. default:{}
  72. },
  73. action:{
  74. type:String
  75. },
  76. steps:{
  77. type:Array
  78. },
  79. tabs:{
  80. type:Array
  81. },
  82. columns:{
  83. type: Array,
  84. required: true
  85. },
  86. labelPosition:{
  87. type:String,
  88. default:'right'
  89. },
  90. labelWidth:{
  91. type:Number,
  92. default:120
  93. },
  94. requireAsteriskPosition:{
  95. type:String,
  96. default:'left'
  97. },
  98. appendWidth:{
  99. type:Number,
  100. default:0
  101. },
  102. onRender:{
  103. type:Function,
  104. default:function(){}
  105. },
  106. onSubmit:{
  107. type:Function,
  108. default:function(){return true}
  109. },
  110. onSuccess:{
  111. type:Function,
  112. default:function(res){}
  113. },
  114. onFail:{
  115. type:Function,
  116. default:function(res){}
  117. },
  118. onStep:{
  119. type:Function,
  120. default:function(res){}
  121. },
  122. onTabChange:{
  123. type:Function,
  124. default:function(res){}
  125. }
  126. },
  127. template:template,
  128. methods:{
  129. reset:function(){
  130. let columns=this.columns;
  131. let promise=[];
  132. for(let i=0;i<columns.length;i++){
  133. //格式化表单
  134. let edit={form:'input',value:'',placeholder:'',blur:'',change:''};
  135. /**简写begin**/
  136. if(columns[i].edit=='hidden' || columns[i].edit=='HIDDEN'){
  137. edit.type='hidden';
  138. columns[i].edit=edit;
  139. }
  140. if(columns[i].edit=='text' || columns[i].edit=='TEXT'){
  141. edit.type='text';
  142. columns[i].edit=edit;
  143. }
  144. if(columns[i].edit=='readonly' || columns[i].edit=='READONLY'){
  145. edit.type='text';
  146. edit.readonly=true;
  147. columns[i].edit=edit;
  148. }
  149. if(columns[i].edit=='password' || columns[i].edit=='PASSWORD'){
  150. edit.type='password';
  151. columns[i].edit=edit;
  152. }
  153. if(columns[i].edit=='textarea' || columns[i].edit=='TEXTAREA'){
  154. edit.type='textarea';
  155. edit.rows=4;
  156. columns[i].edit=edit;
  157. }
  158. if(columns[i].edit=='number' || columns[i].edit=='NUMBER'){
  159. edit.type='number';
  160. columns[i].edit=edit;
  161. }
  162. if(columns[i].edit=='select' || columns[i].edit=='SELECT'){
  163. edit.form='select';
  164. edit.clearable=true;
  165. columns[i].edit=edit;
  166. }
  167. if(columns[i].edit=='selects' || columns[i].edit=='SELECTS'){
  168. edit.form='select';
  169. edit.clearable=true;
  170. edit.multiple=true;
  171. columns[i].edit=edit;
  172. }
  173. if(columns[i].edit=='checkbox' || columns[i].edit=='CHECKBOX'){
  174. edit.form='checkbox';
  175. columns[i].edit=edit;
  176. }
  177. if(columns[i].edit=='radio' || columns[i].edit=='RADIO'){
  178. edit.form='radio';
  179. columns[i].edit=edit;
  180. }
  181. if(columns[i].edit=='editor' || columns[i].edit=='EDITOR'){
  182. edit.form='editor';
  183. edit.width='100%';
  184. edit.height='350px';
  185. columns[i].edit=edit;
  186. }
  187. if(columns[i].edit=='switch' || columns[i].edit=='SWITCH'){
  188. edit.form='switch';
  189. if(columns[i].searchList){
  190. let j=0,k0,k1;
  191. for(let k in columns[i].searchList){
  192. if(j===0)k0=k;
  193. if(j===1)k1=k;
  194. j++;
  195. }
  196. edit.activeValue=k0;
  197. edit.value=k0;
  198. edit.inactiveValue=k1;
  199. }else{
  200. edit.inactiveValue=0;
  201. edit.activeValue=1;
  202. edit.value=1;
  203. }
  204. columns[i].edit=edit;
  205. }
  206. if(columns[i].edit=='date' || columns[i].edit=='DATE'){
  207. edit.form='date-picker';
  208. edit.type='date';
  209. columns[i].edit=edit;
  210. }
  211. if(columns[i].edit=='datetime' || columns[i].edit=='DATETIME'){
  212. edit.form='date-picker';
  213. edit.type='datetime';
  214. columns[i].edit=edit;
  215. }
  216. if(columns[i].edit=='daterange' || columns[i].edit=='DATERANGE'){
  217. edit.form='date-picker';
  218. edit.type='daterange';
  219. columns[i].edit=edit;
  220. }
  221. if(columns[i].edit=='time' || columns[i].edit=='TIME'){
  222. edit.form='time-picker';
  223. columns[i].edit=edit;
  224. }
  225. if(columns[i].edit=='timerange' || columns[i].edit=='TIMERANGE'){
  226. edit.form='time-picker';
  227. edit.isRange=true;
  228. columns[i].edit=edit;
  229. }
  230. if(columns[i].edit=='area' || columns[i].edit=='AREA'){
  231. edit.form='cascader';
  232. edit.url='ajax/area';
  233. edit.level=3;
  234. columns[i].edit=edit;
  235. }
  236. if(columns[i].edit=='category' || columns[i].edit=='CATEGORY'){
  237. edit.form='cascader';
  238. edit.url='ajax/category';
  239. columns[i].edit=edit;
  240. }
  241. if(columns[i].edit=='image' || columns[i].edit=='IMAGE'){
  242. edit.form='attachment';
  243. edit.limit=1;
  244. columns[i].edit=edit;
  245. }
  246. if(columns[i].edit=='images' || columns[i].edit=='IMAGES'){
  247. edit.form='attachment';
  248. edit.limit=10;
  249. columns[i].edit=edit;
  250. }
  251. if(columns[i].edit=='file' || columns[i].edit=='FILE'){
  252. let mimetype=Yunqi.config.upload.mimetype.split(',');
  253. let accept=[];
  254. mimetype.forEach(res=>{
  255. accept.push('.'+res);
  256. });
  257. edit.form='files';
  258. edit.accept=accept.join(',');
  259. edit.multiple=false;
  260. edit.limit=1;
  261. edit.category='';
  262. edit.disks='local_public';
  263. columns[i].edit=edit;
  264. }
  265. if(columns[i].edit=='files' || columns[i].edit=='FILES'){
  266. let mimetype=Yunqi.config.upload.mimetype.split(',');
  267. let accept=[];
  268. mimetype.forEach(res=>{
  269. accept.push('.'+res);
  270. });
  271. edit.form='files';
  272. edit.accept=accept.join(',');
  273. edit.multiple=true;
  274. edit.limit=10;
  275. edit.category='';
  276. edit.disks='local_public';
  277. columns[i].edit=edit;
  278. }
  279. if(columns[i].edit=='fieldlist' || columns[i].edit=='FIELDLIST'){
  280. edit.form='fieldlist';
  281. edit.value=null;
  282. columns[i].edit=edit;
  283. }
  284. if(columns[i].edit=='slot' || columns[i].edit=='SLOT'){
  285. edit.form='slot';
  286. columns[i].edit=edit;
  287. }
  288. /**简写end**/
  289. if(typeof columns[i].edit=='object'){
  290. for(let k in columns[i].edit){
  291. if(k=='blur' || k=='change'){
  292. continue;
  293. }
  294. if(typeof columns[i].edit[k]=='string' && k!='value' && k!='url'){
  295. columns[i].edit[k]=columns[i].edit[k].toLowerCase();
  296. }
  297. }
  298. if(columns[i].edit.form=='cascader'){
  299. columns[i].edit.props=Object.assign({expandTrigger:'hover',multiple:false,children:'childlist',value:'id',label:'name',lazy:false},columns[i].edit.props);
  300. if(columns[i].edit.url && columns[i].edit.level){
  301. columns[i].edit.props.lazy=true;
  302. columns[i].edit.props.expandTrigger='click';
  303. let url=columns[i].edit.url;
  304. columns[i].edit.props.lazyLoad=function(node,resolve){
  305. let pid=0;
  306. let level=columns[i].edit.level;
  307. if(node.level){
  308. pid=node.value;
  309. }
  310. Yunqi.ajax.get(url,{pid:pid}).then(res=>{
  311. if(res instanceof Array){
  312. res.map(t=>{
  313. if(node.level>=level-1){
  314. t.leaf=true;
  315. }
  316. return t;
  317. });
  318. resolve(res);
  319. }else{
  320. resolve([]);
  321. }
  322. });
  323. };
  324. delete columns[i].edit.options;
  325. }
  326. if(columns[i].edit.url && !columns[i].edit.level){
  327. let pro=new Promise((resolve,reject)=>{
  328. Yunqi.ajax.get(columns[i].edit.url).then(res=>{
  329. resolve(res);
  330. });
  331. });
  332. promise.push(pro);
  333. }
  334. }
  335. if(columns[i].edit.form=='date-picker'){
  336. if(columns[i].edit.type=='year'){
  337. edit.format='YYYY年';
  338. }
  339. if(columns[i].edit.type=='month'){
  340. edit.format='YYYY年MM月';
  341. }
  342. if(columns[i].edit.type=='daterange') {
  343. edit.shortcuts = [
  344. {text:'今天',value:function(){
  345. const start = new Date();
  346. return [start, start];
  347. }},
  348. {text:'昨天',value:function(){
  349. const start = new Date();
  350. start.setTime(start.getTime()-3600*1000*24*1);
  351. return [start, start];
  352. }},
  353. {text:'最近7天',value:function(){
  354. const end = new Date();
  355. const start = new Date();
  356. start.setTime(start.getTime()-3600*1000*24*6);
  357. return [start, end];
  358. }},
  359. {text:'最近30天',value:function(){
  360. const end = new Date();
  361. const start = new Date();
  362. start.setTime(start.getTime()-3600*1000*24*29);
  363. return [start, end];
  364. }},
  365. {text:'本月',value:function(){
  366. const end = new Date();
  367. const start=new Date(formatDate(end).slice(0,7)+'-01');
  368. return [start, end];
  369. }},
  370. {text:'上月',value:function(){
  371. const currentDate = new Date();
  372. let lastMonth = currentDate.getMonth() - 1;
  373. let year = currentDate.getFullYear();
  374. if (lastMonth < 0) {
  375. year--;
  376. lastMonth = 11;
  377. }
  378. let firstDay = new Date(year, lastMonth, 1);
  379. let lastDay = new Date(year, lastMonth + 1, 0);
  380. return [firstDay, lastDay];
  381. }},
  382. {text:'今年',value:function(){
  383. let currentDate = new Date();
  384. let year = currentDate.getFullYear();
  385. let start = new Date(year, 0, 1);
  386. let end = new Date(year, 11, 31);
  387. return [start, end];
  388. }},
  389. {text:'去年',value:function(){
  390. let currentDate = new Date();
  391. let year = currentDate.getFullYear() - 1;
  392. let start = new Date(year, 0, 1);
  393. let end = new Date(year, 11, 31);
  394. return [start, end];
  395. }},
  396. ];
  397. }
  398. }
  399. if(columns[i].title){
  400. //定义placeholder
  401. edit.placeholder='请输入'+columns[i].title;
  402. if(columns[i].edit.form=='time' || columns[i].edit.form=='select' || columns[i].edit.form=='selectpage' || columns[i].edit.form=='cascader'){
  403. edit.placeholder='请选择'+columns[i].title;
  404. }
  405. }
  406. //如果用户自定义了属性,则优先使用
  407. for(let key in edit){
  408. columns[i].edit[key]=columns[i].edit[key]?columns[i].edit[key]:edit[key];
  409. if(key=='blur' || key=='change'){
  410. let fun=columns[i].edit[key];
  411. if(!fun){
  412. fun=function(){};
  413. columns[i].edit[key]=fun;
  414. }
  415. if(typeof fun=='string'){
  416. columns[i].edit[key]=function(data,row){
  417. if(Yunqi.app[fun]==undefined){
  418. throw new Error('找不到方法:'+fun);
  419. }
  420. Yunqi.app[fun](data,row);
  421. };
  422. }
  423. }
  424. if(columns[i].edit.button && columns[i].edit.button.method){
  425. let fun=columns[i].edit.button.method;
  426. if(typeof fun=='string'){
  427. columns[i].edit.button.method=function(data,row){
  428. if(Yunqi.app[fun]==undefined){
  429. throw new Error('找不到方法:'+fun);
  430. }
  431. Yunqi.app[fun](data,row);
  432. };
  433. }
  434. }
  435. }
  436. }
  437. if(typeof columns[i].searchList=='function'){
  438. columns[i].searchList=columns[i].searchList();
  439. }
  440. }
  441. Promise.all(promise).then(res=>{
  442. let j=0;
  443. for(let i=0;i<columns.length;i++){
  444. //初始化cascader
  445. if(
  446. columns[i].edit
  447. && columns[i].edit.form=='cascader'
  448. && columns[i].edit.url
  449. && !columns[i].edit.props.lazy
  450. ){
  451. columns[i].edit.options=res[j];
  452. j++;
  453. }
  454. }
  455. this.form_.columns=columns;
  456. this.formatData();
  457. this.formatRules();
  458. this.onRender(this.form_.data);
  459. if(this.steps){
  460. this.activeStep=0;
  461. }
  462. });
  463. },
  464. //初始化数据
  465. formatData:function(){
  466. let columns=this.columns;
  467. let data=copyObj(this.data);
  468. for(let i=0;i<columns.length;i++){
  469. if(columns[i].edit){
  470. let value;
  471. //设置默认值
  472. if(columns[i].edit.form=='checkbox' && !columns[i].edit.value){
  473. value=[];
  474. }else if(columns[i].edit.form=='select' && columns[i].edit.multiple && !columns[i].edit.value){
  475. value=[];
  476. }else if(columns[i].edit.form=='date-picker' && columns[i].edit.type=='dates' && !columns[i].edit.value){
  477. value=[];
  478. }else if(columns[i].edit.form=='cascader' && !columns[i].edit.value){
  479. value=[];
  480. }else if(columns[i].edit.form=='files' && !columns[i].edit.value){
  481. value=[];
  482. }else if(columns[i].edit.form=='selectpage' && columns[i].edit.multiple && !columns[i].edit.value){
  483. value=[];
  484. }else if(columns[i].edit.value && columns[i].edit.value instanceof Object && typeof columns[i].edit.value=='object'){
  485. value=copyObj(columns[i].edit.value);
  486. }else if(columns[i].edit.value && columns[i].edit.value instanceof Object && typeof columns[i].edit.value=='function'){
  487. value=columns[i].edit.value(this.data);
  488. }else{
  489. value=columns[i].edit.value;
  490. }
  491. //替换默认值
  492. value=getValue(data,columns[i].field,value);
  493. //根据表单类型修改表单项目的值
  494. if(columns[i].edit.form=='files'){
  495. if(value && typeof value=='string'){
  496. let files=value.split(',');
  497. value=[];
  498. files.forEach(res=>{
  499. let locase=res.toLowerCase();
  500. if(locase.endsWith('.png') || locase.endsWith('.jpg') || locase.endsWith('.jpeg') || locase.endsWith('.gif') || locase.endsWith('.bmp')){
  501. value.push({
  502. name:'',
  503. url:res,
  504. postUrl:res
  505. });
  506. }else{
  507. value.push({
  508. name:'',
  509. url:getfileImage(res),
  510. postUrl:res
  511. });
  512. }
  513. });
  514. }
  515. if(!value){
  516. value=[];
  517. }
  518. }
  519. if(columns[i].edit.form=='select' && columns[i].edit.multiple && typeof value=='string'){
  520. value=value.split(',');
  521. if(columns[i].searchList){
  522. value=changeCheckboxValue(columns[i].searchList,value);
  523. }
  524. }
  525. if(columns[i].edit.form=='select' && columns[i].edit.multiple && value instanceof Array){
  526. value=value.map(res=>{
  527. return res+'';
  528. });
  529. if(columns[i].searchList){
  530. value=changeCheckboxValue(columns[i].searchList,value);
  531. }
  532. }
  533. if(columns[i].edit.form=='select' && columns[i].edit.multiple && columns[i].edit.checkAll){
  534. value=Object.keys(columns[i].searchList);
  535. }
  536. if(columns[i].edit.form=='checkbox' && typeof value=='string'){
  537. value=value.split(',');
  538. if(columns[i].searchList){
  539. value=changeCheckboxValue(columns[i].searchList,value);
  540. }
  541. }
  542. if(columns[i].edit.form=='checkbox' && value instanceof Array){
  543. value=value.map(res=>{
  544. return res+'';
  545. });
  546. if(columns[i].searchList){
  547. value=changeCheckboxValue(columns[i].searchList,value);
  548. }
  549. }
  550. if(columns[i].edit.form=='input' && columns[i].edit.type=='password'){
  551. value='';
  552. }
  553. if(columns[i].edit.form=='date-picker' && columns[i].edit.type=='date' && value && typeof value=='string'){
  554. value=new Date(value);
  555. }
  556. if(columns[i].edit.form=='date-picker' && columns[i].edit.type=='datetime' && value && typeof value=='string'){
  557. value=new Date(value);
  558. }
  559. if(columns[i].edit.form=='date-picker' && columns[i].edit.type=='date' && value && typeof value=='number'){
  560. value=new Date(value*1000);
  561. }
  562. if(columns[i].edit.form=='date-picker' && columns[i].edit.type=='datetime' && value && typeof value=='number'){
  563. value=new Date(value*1000);
  564. }
  565. if(columns[i].edit.form=='date-picker' && columns[i].edit.type=='dates'){
  566. if(!value){
  567. value=[];
  568. }else if(typeof value=='string'){
  569. value=value.split(',');
  570. }
  571. value=value.map(res=>{
  572. res=new Date(res);
  573. return res;
  574. });
  575. }
  576. if(columns[i].edit.form=='date-picker' && columns[i].edit.type=='year' && value){
  577. let date=formatDate(new Date());
  578. value=new Date(value+date.slice(4));
  579. }
  580. if(columns[i].edit.form=='date-picker' && columns[i].edit.type=='month' && value){
  581. let date=formatDate(new Date());
  582. value=new Date(value+date.slice(7));
  583. }
  584. if(columns[i].edit.form=='date-picker' && columns[i].edit.type=='daterange' && value){
  585. if(typeof value=='string'){
  586. value=value.split(',');
  587. }
  588. value=value.map(res=>{
  589. res=new Date(res);
  590. return res;
  591. });
  592. }
  593. if(columns[i].edit.form=='time-picker' && !columns[i].edit.isRange && value){
  594. let date=formatDate(new Date());
  595. value=new Date(date+' '+value);
  596. }
  597. if(columns[i].edit.form=='time-picker' && columns[i].edit.isRange && value){
  598. if(typeof value=='string'){
  599. value=value.split(',');
  600. }
  601. let date=formatDate(new Date());
  602. value=value.map(res=>{
  603. res=new Date(date+' '+res);
  604. return res;
  605. });
  606. }
  607. if(typeof value=='number'){
  608. value=value.toString();
  609. }
  610. data[columns[i].field]=value;
  611. }
  612. if(this.steps && columns[i].step==undefined){
  613. columns[i].step=1;
  614. }
  615. }
  616. this.form_.data=data;
  617. },
  618. //格式化rules
  619. formatRules:function () {
  620. let rules={};
  621. let columns=this.columns;
  622. for(let i=0;i<columns.length;i++){
  623. if(columns[i].rules instanceof Object){
  624. if(columns[i].rules instanceof Function){
  625. const trigger = (columns[i].edit.form === 'input') ? 'blur' : 'change';
  626. const validator=columns[i].rules;
  627. rules[columns[i].field]=[{validator,trigger}];
  628. }else if(Array.isArray(columns[i].rules)){
  629. rules[columns[i].field]=copyObj(columns[i].rules);
  630. }else{
  631. rules[columns[i].field]=[copyObj(columns[i].rules)];
  632. }
  633. }
  634. if(typeof columns[i].rules=='string'){
  635. const ruleArr = columns[i].rules.split(';');
  636. const ruleList = [];
  637. ruleArr.forEach(rule => {
  638. const trigger = (columns[i].edit.form === 'input') ? 'blur' : 'change';
  639. let validator;
  640. let message;
  641. let required;
  642. if(rule.startsWith('required')){
  643. required=true;
  644. validator = (rule, value, callback) => {
  645. if(value==='' || value===null){
  646. callback(new Error());
  647. }else if(value instanceof Array && value.length==0){
  648. callback(new Error('请至少选择一项'));
  649. }else{
  650. callback();
  651. }
  652. };
  653. message=columns[i].title+'不能为空!';
  654. }else if(rule.startsWith('checked')){
  655. let f=rule.indexOf('~')==-1;
  656. let d=rule.slice(8);
  657. let drr=d.slice(0,d.length-1).split('~');
  658. validator = (rule, value, callback) => {
  659. if(drr[0] && f && value.length!=parseInt(drr[0])){
  660. callback(new Error(`请选择${drr[0]}项`));
  661. }else if(drr[0] && value.length<parseInt(drr[0])){
  662. callback(new Error(`至少选择${drr[0]}项`));
  663. }else if(drr[1] && value.length>parseInt(drr[1])){
  664. callback(new Error(`至多选择${drr[1]}项`));
  665. }else if (!value || value.length === 0) {
  666. callback(new Error(`至少选择一项`));
  667. } else {
  668. callback();
  669. }
  670. };
  671. }else if(rule.startsWith('integer')){
  672. validator = (tx, value, callback) => {
  673. if(value==='' || value===null){
  674. callback();
  675. return;
  676. }
  677. if (rule=='integer' && !(/^-?\d+$/.test(value))) {
  678. callback(new Error('请输入整数'));
  679. } else if (rule=='integer(+)' && !(/^[1-9]\d*$/.test(value))) {
  680. callback(new Error('请输入正整数'));
  681. } else if (rule=='integer(+0)' && !(/^(0|[1-9]\d*)$/.test(value))) {
  682. callback(new Error('请输入大于或等于0的整数'));
  683. } else if (rule=='integer(-)' && !(/^(-\d+)$/.test(value))) {
  684. callback(new Error('请输入负整数'));
  685. } else if (rule=='integer(-0)' && !(/^(-\d+|0)$/.test(value))) {
  686. callback(new Error('请输入小于或等于0的整数'));
  687. } else {
  688. callback();
  689. }
  690. };
  691. }else if(rule.startsWith('range')){
  692. validator = (tx, value, callback) => {
  693. if(value==='' || value===null){
  694. callback();
  695. return;
  696. }
  697. let f=rule.indexOf('~')==-1;
  698. let d=rule.slice(6);
  699. let drr=d.slice(0,d.length-1).split('~');
  700. if(drr[0] && Number(value)<Number(drr[0])){
  701. callback(new Error(`请填写不小于${drr[0]}的数`));
  702. }else if(drr[1] && Number(value)>Number(drr[1])){
  703. callback(new Error(`请填写不大于${drr[1]}的数`));
  704. }else {
  705. callback();
  706. }
  707. }
  708. }else if(rule.startsWith('length')){
  709. let f=rule.indexOf('~')==-1;
  710. let d=rule.slice(7);
  711. let drr=d.slice(0,d.length-1).split('~');
  712. validator = (rule, value, callback) => {
  713. if(drr[0] && f && value.length!=parseInt(drr[0])){
  714. if(value instanceof Array){
  715. callback(new Error(`请选择${drr[0]}个值`));
  716. }else{
  717. callback(new Error(`请输入${drr[0]}个字符`));
  718. }
  719. }else if(drr[0] && value.length<parseInt(drr[0])){
  720. if(value instanceof Array){
  721. callback(new Error(`至少选择${drr[0]}个值`));
  722. }else{
  723. callback(new Error(`至少输入${drr[0]}个字符`));
  724. }
  725. }else if(drr[1] && value.length>parseInt(drr[1])){
  726. if(value instanceof Array){
  727. callback(new Error(`至多选择${drr[1]}个值`));
  728. }else{
  729. callback(new Error(`至多输入${drr[1]}个字符`));
  730. }
  731. }else {
  732. callback();
  733. }
  734. };
  735. }else if(rule.startsWith('chinaChar')){
  736. validator = (rule, value, callback) => {
  737. if(value==='' || value===null){
  738. callback();
  739. return;
  740. }
  741. for(let j=0;j<value.length;j++){
  742. let s=value.charAt(j);
  743. let reg = /[\u4e00-\u9fa5]{1}/;
  744. if(!reg.test(s)){
  745. callback(new Error());
  746. return;
  747. }
  748. }
  749. callback();
  750. };
  751. message='只能输入中文';
  752. }else if(rule.startsWith('unChinaChar')){
  753. validator = (rule, value, callback) => {
  754. if(value==='' || value===null){
  755. callback();
  756. return;
  757. }
  758. for(let j=0;j<value.length;j++){
  759. let s=value.charAt(j);
  760. let reg = /[\u4e00-\u9fa5]{1}/;
  761. if(reg.test(s)){
  762. callback(new Error());
  763. return;
  764. }
  765. }
  766. callback();
  767. };
  768. message='不能输入中文';
  769. }else if(rule.startsWith('mobile')){
  770. validator = (rule, value, callback) => {
  771. if(value==='' || value===null){
  772. callback();
  773. return;
  774. }
  775. const reg = /^1[3456789]\d{9}$/;
  776. if (!reg.test(value)) {
  777. callback(new Error());
  778. } else {
  779. callback();
  780. }
  781. };
  782. message=`请输入手机号!`;
  783. }else if(rule.startsWith('email')){
  784. validator = (rule, value, callback) => {
  785. if(value==='' || value===null){
  786. callback();
  787. return;
  788. }
  789. const reg = /^[A-Za-z0-9\u4e00-\u9fa5]+@[a-zA-Z0-9_-]+(.[a-zA-Z0-9_-]+)+$/;
  790. if (!reg.test(value)) {
  791. callback(new Error());
  792. } else {
  793. callback();
  794. }
  795. };
  796. message=`请输入邮箱地址!`;
  797. }else if(rule.startsWith('idcard')){
  798. validator = (rule, value, callback) => {
  799. if(value==='' || value===null){
  800. callback();
  801. return;
  802. }
  803. const reg = /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/;
  804. if (!reg.test(value)) {
  805. callback(new Error());
  806. } else {
  807. callback();
  808. }
  809. };
  810. message=`请输入身份证号!`;
  811. }
  812. ruleList.push({required,validator,message,trigger});
  813. });
  814. rules[columns[i].field]=ruleList;
  815. }
  816. }
  817. this.form_.rules=rules;
  818. },
  819. handleSelectCheckAll:function (column){
  820. let field=column.field;
  821. let keys=Object.keys(column.searchList);
  822. if(column.edit.checkAll){
  823. this.setValue(field,keys);
  824. }else{
  825. this.setValue(field,[]);
  826. }
  827. },
  828. handlePictureCardPreview:function (uploadfile){
  829. let img=uploadfile.url;
  830. Yunqi.api.previewImg(img);
  831. },
  832. showField:function (fields){
  833. if(typeof fields=='string'){
  834. fields=[fields];
  835. }
  836. for(let i=0;i<this.form_.columns.length;i++){
  837. if(inArray(fields,this.form_.columns[i].field)){
  838. delete this.form_.columns[i].visible;
  839. }
  840. }
  841. },
  842. hideField:function (fields){
  843. if(typeof fields=='string'){
  844. fields=[fields];
  845. }
  846. for(let i=0;i<this.form_.columns.length;i++){
  847. if(inArray(fields,this.form_.columns[i].field)){
  848. this.form_.columns[i].visible=false;
  849. }
  850. }
  851. },
  852. setField:function (field,key,value){
  853. for(let i=0;i<this.form_.columns.length;i++){
  854. if(this.form_.columns[i].field==field){
  855. this.form_.columns[i][key]=value;
  856. if(key=='edit' && value instanceof Object && value.value!==undefined){
  857. this.form_.data[field]=value.value;
  858. }
  859. return;
  860. }
  861. }
  862. },
  863. setValue:function (key,value){
  864. if(typeof value=='number'){
  865. value=value.toString();
  866. }
  867. this.form_.data[key]=value;
  868. },
  869. getValue:function (key){
  870. return this.form_.data[key];
  871. },
  872. setError:function (field,message){
  873. for(let i=0;i<this.form_.columns.length;i++){
  874. if(this.form_.columns[i].field==field){
  875. let edit=this.form_.columns[i].edit;
  876. edit.error=message;
  877. this.$refs.formRef.scrollToField(field);
  878. return;
  879. }
  880. }
  881. },
  882. getFormColumn:function (field){
  883. for(let i=0;i<this.form_.columns.length;i++){
  884. if(this.form_.columns[i].field==field){
  885. return this.form_.columns[i];
  886. }
  887. }
  888. },
  889. changeFieldlist:function (r){
  890. this.form_.data[r.field]=r.value;
  891. let column=this.getFormColumn(r.field);
  892. column.edit.change(this.form_.data[r.field],this.form_.data);
  893. },
  894. changeSelectpage:function (r){
  895. this.form_.data[r.field]=r.value;
  896. let column=this.getFormColumn(r.field);
  897. column.edit.change(this.form_.data[r.field],this.form_.data);
  898. },
  899. changeAttachment:function (r){
  900. this.form_.data[r.field]=r.value;
  901. let column=this.getFormColumn(r.field);
  902. column.edit.change(this.form_.data[r.field],this.form_.data);
  903. },
  904. changeEditor:function (r){
  905. this.form_.data[r.field]=r.value;
  906. let column=this.getFormColumn(r.field);
  907. column.edit.change(this.form_.data[r.field],this.form_.data);
  908. },
  909. isYesOrNo:function (searchList){
  910. let r=true;
  911. let i=0;
  912. for(let k in searchList){
  913. if(i===0 && k!=0 && k!='0'){
  914. r=false;
  915. }
  916. if(i===1 && k!=1 && k!='1'){
  917. r=false;
  918. }
  919. if(i===2){
  920. r=false;
  921. }
  922. i++;
  923. }
  924. return r;
  925. },
  926. fileUploadSuccess:function (e,f){
  927. if(!e.code){
  928. Yunqi.message.error(__(e.msg));
  929. return;
  930. }
  931. f.url=e.data.thumburl;
  932. f.postUrl=e.data.fullurl;
  933. },
  934. fileUploadBefore:function (file){
  935. let maxsize=Number(Yunqi.config.upload.maxsize);
  936. if(file.size>1024*1024*maxsize){
  937. Yunqi.message.error(__('文件大小不能超过'+maxsize+'mb'));
  938. return false;
  939. }
  940. return true;
  941. },
  942. parsePostValue:function (postdata,key,value,havaname=false){
  943. if(value===undefined || value===null){
  944. value='';
  945. }
  946. if(value instanceof Object && Object.keys(value).length==0){
  947. value='';
  948. }
  949. if(havaname){
  950. postdata[havaname]=value;
  951. }else{
  952. postdata['row['+key+']']=value;
  953. }
  954. },
  955. tabChange:function (){
  956. this.onTabChange(this.activeTab,this.form_.data);
  957. },
  958. nextStep:function(){
  959. let columns=this.form_.columns;
  960. let promiseAll=[];
  961. for(let i=0;i<columns.length;i++){
  962. if(columns[i].edit && columns[i].step==this.activeStep){
  963. let promise=new Promise((resolve,reject)=>{
  964. this.$refs.formRef.validateField(columns[i].field,valid=>{
  965. if(valid){
  966. resolve();
  967. }else{
  968. reject();
  969. }
  970. });
  971. });
  972. promiseAll.push(promise);
  973. }
  974. }
  975. Promise.all(promiseAll).then(()=>{
  976. this.activeStep++;
  977. this.onStep(this.activeStep,this.form_.data);
  978. });
  979. },
  980. preStep:function (){
  981. this.activeStep--;
  982. this.onStep(this.activeStep,this.form_.data);
  983. },
  984. submit:function (e) {
  985. let tokenEle=document.querySelector('input[name="__token__"]');
  986. let token=tokenEle?tokenEle.value:'';
  987. this.$refs.formRef.validate((valid, fields)=>{
  988. if(valid){
  989. let r=this.onSubmit(this.form_.data);
  990. if(r===true){
  991. let action=this.action;
  992. if(!action){
  993. action=Yunqi.config.url;
  994. }
  995. let postdata={};
  996. for(let i=0;i<this.columns.length;i++){
  997. let havaname=false;
  998. let isFile=false;
  999. let isFieldList=false;
  1000. let dateType=false;
  1001. let isTime=false;
  1002. if(this.columns[i].edit==undefined){
  1003. continue;
  1004. }
  1005. if(this.columns[i].edit.name===false){
  1006. continue
  1007. }
  1008. if(this.columns[i].edit.name!=undefined){
  1009. havaname=this.columns[i].edit.name;
  1010. }
  1011. if(this.columns[i].edit.form=='files'){
  1012. isFile=true;
  1013. }
  1014. if(this.columns[i].edit.form=='fieldlist'){
  1015. isFieldList=true;
  1016. }
  1017. if(this.columns[i].edit.form=='date-picker'){
  1018. dateType=this.columns[i].edit.type;
  1019. }
  1020. if(this.columns[i].edit.form=='time-picker'){
  1021. isTime=true;
  1022. }
  1023. let issetpost=false;
  1024. if(isFile){
  1025. issetpost=true;
  1026. let r=[];
  1027. let fileValue=this.form_.data[this.columns[i].field];
  1028. if(fileValue){
  1029. for(let i in fileValue){
  1030. r.push(fileValue[i].postUrl);
  1031. }
  1032. }
  1033. if(r.length>0){
  1034. this.parsePostValue(postdata,this.columns[i].field,r.join(','),havaname);
  1035. }
  1036. }
  1037. if(dateType){
  1038. issetpost=true;
  1039. let dateValue=this.form_.data[this.columns[i].field];
  1040. if(dateValue){
  1041. switch (dateType){
  1042. case 'date':
  1043. dateValue=formatDate(dateValue);
  1044. break;
  1045. case 'datetime':
  1046. dateValue=formatDateTime(dateValue);
  1047. break;
  1048. case 'dates':
  1049. if(dateValue.length>0){
  1050. dateValue=dateValue.map(res=>{
  1051. res=formatDate(res);
  1052. return res;
  1053. });
  1054. }else{
  1055. dateValue='';
  1056. }
  1057. break;
  1058. case 'year':
  1059. dateValue=dateValue.getFullYear();
  1060. break;
  1061. case 'month':
  1062. dateValue=formatDate(dateValue).slice(0,7);
  1063. break;
  1064. case 'daterange':
  1065. if(dateValue.length){
  1066. let begin1=formatDate(dateValue[0])+' 00:00:00';
  1067. let end1=formatDate(dateValue[1])+' 23:59:59';
  1068. dateValue=[begin1,end1];
  1069. }else{
  1070. dateValue='';
  1071. }
  1072. break;
  1073. default:
  1074. break;
  1075. }
  1076. this.parsePostValue(postdata,this.columns[i].field,dateValue,havaname);
  1077. }
  1078. }
  1079. if(isTime){
  1080. issetpost=true;
  1081. let timeValue=this.form_.data[this.columns[i].field];
  1082. if(timeValue){
  1083. if(timeValue instanceof Array){
  1084. timeValue=[formatTime(timeValue[0]),formatTime(timeValue[1])];
  1085. }else{
  1086. timeValue=formatTime(timeValue);
  1087. }
  1088. this.parsePostValue(postdata,this.columns[i].field,timeValue,havaname);
  1089. }
  1090. }
  1091. if(isFieldList){
  1092. issetpost=true;
  1093. let strlist=JSON.stringify(this.form_.data[this.columns[i].field]);
  1094. if(strlist!='{}' && strlist!='[]'){
  1095. this.parsePostValue(postdata,this.columns[i].field,strlist,havaname);
  1096. }
  1097. }
  1098. if(!issetpost){
  1099. let value=this.form_.data[this.columns[i].field]
  1100. this.parsePostValue(postdata,this.columns[i].field,value,havaname);
  1101. }
  1102. }
  1103. if(token){
  1104. postdata.__token__=token;
  1105. }
  1106. Yunqi.ajax.post(action,postdata,true).then(res=>{
  1107. this.onSuccess(res);
  1108. Yunqi.api.closelayer(Yunqi.app.window.id,true);
  1109. }).catch(err=>{
  1110. this.onFail(err);
  1111. });
  1112. }
  1113. }else{
  1114. let keys=Object.keys(fields);
  1115. for(let i=0;i<this.columns.length;i++){
  1116. let field=this.columns[i].field;
  1117. let tab=this.columns[i].tab;
  1118. if(tab && inArray(keys,field)){
  1119. this.activeTab=tab;
  1120. }
  1121. }
  1122. }
  1123. });
  1124. }
  1125. },
  1126. };