my_form.vue 34 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232
  1. <template>
  2. <view>
  3. <view class="requiredFieldOnly-head" v-if="requiredFieldOnly">
  4. <view class="label"> 基本信息 </view>
  5. <view class="content">
  6. 仅显示必填信息<text style="padding: 0 2.5px" />
  7. <u-switch activeColor="#C40C24" v-model="unShowAll" />
  8. </view>
  9. </view>
  10. <slot name="head" />
  11. <block v-for="(item, index) in list" :key="item.key">
  12. <block v-if="item.isMust || !unShowAll">
  13. <!-- 文本输入 -->
  14. <view
  15. class="input-box"
  16. v-if="item.type == 'text'"
  17. :style="{
  18. marginTop: tovw(item.marginTop || 0),
  19. opacity: item.disabled ? 0.7 : 1,
  20. }"
  21. @click="focusLabel = item.label"
  22. >
  23. <view class="box" :class="item.unBorBot ? '' : 'borBot'">
  24. <view class="label">
  25. <text class="must" v-if="item.isMust">*</text>
  26. {{ item.label }}:
  27. </view>
  28. <view class="content-box" style="flex: 1">
  29. <view
  30. class="content"
  31. style="display: flex; flex: 1; box-sizing: border-box"
  32. >
  33. <input
  34. v-if="item.inputmode == 'number'"
  35. type="number"
  36. :disabled="item.disabled"
  37. placeholder-style="color: #BBBBBB;font-family: Source Han Sans SC, Source Han Sans SC;"
  38. :focus="focusLabel == item.label"
  39. :placeholder="item.placeholder || '请填写' + item.label"
  40. :value="item.value"
  41. style="flex: 1"
  42. @input="onInput($event, index)"
  43. :maxlength="item.maxlength || '499'"
  44. confirm-type="done"
  45. />
  46. <input
  47. v-else-if="item.inputmode == 'digit'"
  48. type="digit"
  49. :disabled="item.disabled"
  50. placeholder-style="color: #BBBBBB;font-family: Source Han Sans SC, Source Han Sans SC;"
  51. :focus="focusLabel == item.label"
  52. :placeholder="item.placeholder || '请填写' + item.label"
  53. :value="item.value"
  54. style="flex: 1"
  55. @input="onInput($event, index)"
  56. :maxlength="item.maxlength || '499'"
  57. confirm-type="done"
  58. />
  59. <textarea
  60. v-else
  61. :disabled="item.disabled"
  62. placeholder-style="color: #BBBBBB;font-family: Source Han Sans SC, Source Han Sans SC;"
  63. auto-height
  64. type="text"
  65. :focus="focusLabel == item.label"
  66. :placeholder="item.placeholder || '请填写' + item.label"
  67. :value="item.value"
  68. style="flex: 1; width: 0; box-sizing: border-box"
  69. @input="onInput($event, index)"
  70. :maxlength="item.maxlength || '499'"
  71. confirm-type="done"
  72. />
  73. <icon
  74. v-if="item.value && !item.disabled"
  75. class="icon"
  76. type="clear"
  77. size="3.733vw"
  78. @click="onClearInput(index)"
  79. />
  80. <view style="margin-left: 6px" v-if="item.getPhoneNumber">
  81. <u-button
  82. color="#C30D23"
  83. size="small"
  84. open-type="getPhoneNumber"
  85. @click.stop=""
  86. @getphonenumber="butGetphonenumber($event, index)"
  87. >
  88. 获取微信
  89. <text
  90. class="iconfont icon-dianhua-hui"
  91. style="font-size: 12px; margin-left: 3px"
  92. />
  93. </u-button>
  94. </view>
  95. </view>
  96. <view v-if="item.errText" class="err-text">
  97. <icon
  98. class="icon"
  99. color="#E3041F"
  100. type="clear"
  101. size="2.733vw"
  102. />
  103. {{ item.errText }}
  104. </view>
  105. </view>
  106. </view>
  107. </view>
  108. <!-- 文本域 -->
  109. <view class="textarea-box" v-else-if="item.type == 'textarea'">
  110. <textarea
  111. class="textarea"
  112. :class="item.unBorBot ? '' : 'borBot'"
  113. :disabled="item.disabled"
  114. placeholder-style="color: #BBBBBB;font-family: Source Han Sans SC, Source Han Sans SC;"
  115. type="text"
  116. :placeholder="item.placeholder || '请填写' + item.label"
  117. :value="item.value"
  118. @input="onInput($event, index)"
  119. :maxlength="item.maxlength || '499'"
  120. confirm-type="done"
  121. />
  122. </view>
  123. <!-- 显示标题文本域 参考意见反馈 -->
  124. <view
  125. class="textarea-box2"
  126. v-else-if="item.type == 'textarea2'"
  127. :style="{ marginTop: tovw(item.marginTop || 0) }"
  128. >
  129. <view class="label">
  130. <text class="must" v-if="item.isMust">*</text>
  131. {{ item.label }}:
  132. </view>
  133. <textarea
  134. class="textarea"
  135. :class="item.unBorBot ? '' : 'borBot'"
  136. :disabled="item.disabled"
  137. placeholder-style="color: #BBBBBB;font-family: Source Han Sans SC, Source Han Sans SC;"
  138. type="text"
  139. :placeholder="item.placeholder || '请填写' + item.label"
  140. :value="item.value"
  141. @input="onInput($event, index)"
  142. :maxlength="item.maxlength || '499'"
  143. confirm-type="done"
  144. />
  145. </view>
  146. <!-- 自定义选项分类 -->
  147. <view
  148. class="custom-class-box"
  149. v-else-if="item.type == 'customClass'"
  150. :style="{
  151. marginTop: tovw(item.marginTop || 0),
  152. paddingBottom: item.showBorBot ? 0 : '10px',
  153. }"
  154. >
  155. <view class="head">
  156. <view class="label">
  157. <text class="must" style="color: #e3041f" v-if="item.isMust"
  158. >*</text
  159. >
  160. {{ item.label }}
  161. </view>
  162. <view class="state">
  163. {{ item.isMultipleChoice ? "可多选" : "仅单选" }}
  164. </view>
  165. </view>
  166. <view class="options">
  167. <view
  168. class="option"
  169. :class="
  170. item.isMultipleChoice
  171. ? item.value.includes(option.value)
  172. ? 'active'
  173. : ''
  174. : item.value == option.value
  175. ? 'active'
  176. : ''
  177. "
  178. v-for="option in item.list"
  179. :key="option.value"
  180. hover-class="navigator-hover"
  181. @click="changOptions(option.value, index)"
  182. >
  183. {{ option.remarks }}
  184. </view>
  185. </view>
  186. <view class="borBot" v-if="item.showBorBot" style="height: 10px" />
  187. </view>
  188. <!-- 选择所在地区 -->
  189. <picker
  190. class="region"
  191. @change="selectRegion($event, index)"
  192. mode="region"
  193. :disabled="item.disabled"
  194. :value="item.value"
  195. v-else-if="item.type == 'region'"
  196. :style="{
  197. marginTop: tovw(item.marginTop || 0),
  198. opacity: item.disabled ? 0.7 : 1,
  199. }"
  200. >
  201. <view class="box" :class="item.unBorBot ? '' : 'borBot'">
  202. <view class="label">
  203. <text class="must" v-if="item.isMust">*</text>
  204. {{ item.label }}:
  205. </view>
  206. <view class="content-box">
  207. <view class="value" v-if="item.value.length">
  208. {{ item.value.join(",") }}
  209. </view>
  210. <view v-else class="placeholder" hover-class="none">
  211. {{ item.placeholder || "请选择" + item.label }}
  212. </view>
  213. <view
  214. v-if="!item.disabled"
  215. class="iconfont icon-a-wodetiaozhuan"
  216. />
  217. </view>
  218. </view>
  219. </picker>
  220. <!-- 日期 -->
  221. <picker
  222. class="region"
  223. @change="selectRegion($event, index)"
  224. mode="date"
  225. :disabled="item.disabled"
  226. :value="item.value"
  227. v-else-if="item.type == 'date'"
  228. :style="{
  229. marginTop: tovw(item.marginTop || 0),
  230. opacity: item.disabled ? 0.7 : 1,
  231. }"
  232. >
  233. <view class="box" :class="item.unBorBot ? '' : 'borBot'">
  234. <view class="label">
  235. <text class="must" v-if="item.isMust">*</text>
  236. {{ item.label }}:
  237. </view>
  238. <view class="content-box">
  239. <view class="value" v-if="item.value">
  240. {{ item.value }}
  241. </view>
  242. <view v-else class="placeholder" hover-class="none">
  243. {{ item.placeholder || "请选择" + item.label }}
  244. </view>
  245. <view
  246. v-if="!item.disabled"
  247. class="iconfont icon-a-wodetiaozhuan"
  248. />
  249. </view>
  250. </view>
  251. </picker>
  252. <!-- 上传附件 -->
  253. <view
  254. class="custom-class-box"
  255. v-else-if="item.type == 'upload'"
  256. :style="{ marginTop: tovw(item.marginTop || 0) }"
  257. >
  258. <view class="head">
  259. <view class="label">
  260. <text class="must" v-if="item.isMust">*</text>
  261. {{ item.label }}
  262. </view>
  263. <view class="state">
  264. {{ item.placeholder }}
  265. </view>
  266. </view>
  267. <view class="content">
  268. <view
  269. class="file-box"
  270. v-for="file in item.value"
  271. :key="file.attachmentid"
  272. >
  273. <image
  274. class="image"
  275. v-if="file.fileType == 'image'"
  276. :src="file.url"
  277. mode="aspectFill"
  278. lazy-load="true"
  279. @click="previewImg(file)"
  280. />
  281. <video
  282. v-else-if="file.fileType == 'video'"
  283. class="video"
  284. :poster="file.subfiles[0].url"
  285. :src="file.url"
  286. />
  287. <image
  288. class="delete"
  289. @click.stop="deleteFile(file, index)"
  290. src="https://yossys06593.obs.cn-east-3.myhuaweicloud.com:443/202404241713944430197B47af9b2f.png"
  291. mode="widthFix"
  292. />
  293. </view>
  294. <My_upload
  295. v-if="item.allowUpload"
  296. :showLoading="false"
  297. :maxCount="item.maxCount || 99"
  298. :accept="item.accept"
  299. @uploadCallback="uploadCallback($event, index)"
  300. @onLoading="onUploadLoading($event, index)"
  301. >
  302. <view
  303. class="upload-box"
  304. v-if="
  305. item.maxCount
  306. ? item.value.length != item.maxCount
  307. : item.value.length != 99
  308. "
  309. hover-class="navigator-hover"
  310. >
  311. <u-loading-icon v-if="item.loading" />
  312. <text v-else class="iconfont icon-xiazai" />
  313. <text style="margin-left: 5px">上传</text>
  314. </view>
  315. </My_upload>
  316. </view>
  317. </view>
  318. <!-- 开关 -->
  319. <view class="region" v-else-if="item.type == 'switch'">
  320. <view class="box" :class="item.unBorBot ? '' : 'borBot'">
  321. <view class="label">
  322. <text class="must" v-if="item.isMust">*</text>
  323. {{ item.label }}:
  324. </view>
  325. <view class="content-box">
  326. <view />
  327. <u-switch
  328. activeColor="#70D95D"
  329. v-model="item.value"
  330. :disabled="item.disabled"
  331. @change="switchChange($event, index)"
  332. />
  333. </view>
  334. </view>
  335. </view>
  336. <!-- 性别 -->
  337. <view class="region" v-else-if="item.type == 'sex'">
  338. <view class="box" :class="item.unBorBot ? '' : 'borBot'">
  339. <view class="label">
  340. <text class="must" v-if="item.isMust">*</text>
  341. {{ item.label }}:
  342. </view>
  343. <u-radio-group
  344. v-model="item.value"
  345. placement="row"
  346. @change="groupChange($event, index)"
  347. >
  348. <u-radio
  349. :customStyle="{ marginRight: tovw(60) }"
  350. label="男"
  351. name="男"
  352. />
  353. <u-radio label="女" name="女" />
  354. </u-radio-group>
  355. </view>
  356. </view>
  357. <!-- 单选 -->
  358. <view class="region" v-else-if="item.type == 'radio'">
  359. <view class="box" :class="item.unBorBot ? '' : 'borBot'">
  360. <view class="label">
  361. <text class="must" v-if="item.isMust">*</text>
  362. {{ item.label }}:
  363. </view>
  364. <u-radio-group
  365. v-model="item.value"
  366. :placement="item.placement || 'row'"
  367. @change="groupChange($event, index)"
  368. >
  369. <u-radio
  370. v-for="option in item.options"
  371. :customStyle="{
  372. marginRight: tovw(
  373. option.marginRight || item.marginRight || 0
  374. ),
  375. marginTop: tovw(option.marginTop || item.marginTop || 0),
  376. }"
  377. :key="option.label"
  378. :label="option.label"
  379. :name="option.name"
  380. />
  381. </u-radio-group>
  382. </view>
  383. </view>
  384. <!-- 路由选择器 -->
  385. <view
  386. class="region"
  387. v-else-if="item.type == 'route'"
  388. :style="{
  389. marginTop: tovw(item.marginTop || 0),
  390. opacity: item.disabled ? 0.7 : 1,
  391. }"
  392. @click="item.disabled ? '' : toRoute(item, index)"
  393. >
  394. <view class="box" :class="item.unBorBot ? '' : 'borBot'">
  395. <view class="label">
  396. <text class="must" v-if="item.isMust">*</text>
  397. {{ item.label }}:
  398. </view>
  399. <view class="content-box2">
  400. <view class="value" v-if="item.showValue.length">
  401. {{ item.showValue.join(",") }}
  402. </view>
  403. <view v-else class="placeholder" hover-class="none">
  404. {{ item.placeholder || "请选择" + item.label }}
  405. </view>
  406. <view
  407. v-if="!item.disabled"
  408. class="iconfont icon-a-wodetiaozhuan"
  409. />
  410. </view>
  411. </view>
  412. </view>
  413. <!-- 标签 -->
  414. <view
  415. class="tag-box custom-class-box"
  416. v-else-if="item.type == 'tag'"
  417. :style="{ marginTop: tovw(item.marginTop || 0) }"
  418. >
  419. <text class="label">{{ item.label }}</text>
  420. <view class="tag-list">
  421. <view class="tag" v-for="tag in item.value" :key="tag">
  422. <text>{{ tag }}</text>
  423. <view @click="delTag(tag, index)" class="del">x</view>
  424. </view>
  425. <view>
  426. <u-modal
  427. :title="item.label"
  428. :show="showTagModal"
  429. style="flex: 0 !important"
  430. confirmColor="#C30D23"
  431. ref="uModal"
  432. showCancelButton
  433. :asyncClose="false"
  434. @confirm="addTagSend(index)"
  435. @cancel="showTagModal = false"
  436. >
  437. <view class="slot-content">
  438. <view
  439. v-if="item.errText"
  440. class="err-text"
  441. style="margin-bottom: 10px"
  442. >
  443. <icon
  444. class="icon"
  445. color="#E3041F"
  446. type="clear"
  447. size="2.733vw"
  448. />
  449. {{ item.errText }}
  450. </view>
  451. <u--input
  452. :maxlength="item.maxlength ? item.maxlength : '99999'"
  453. :focus="showUModal"
  454. @input="onTagInput($event, index)"
  455. :placeholder="item.placeholder || '请输入'"
  456. v-model="tagValue"
  457. border="bottom"
  458. clearable
  459. />
  460. </view>
  461. </u-modal>
  462. <view class="add-tag" @click="showTagModal = true">+ 添加</view>
  463. </view>
  464. </view>
  465. </view>
  466. </block>
  467. </block>
  468. </view>
  469. </template>
  470. <script>
  471. import { formattedFiles, viewImage } from "../utils/settleFiles.js";
  472. export default {
  473. name: "my_form",
  474. props: {
  475. form: {
  476. type: Array,
  477. default: [],
  478. },
  479. isUncomplete: {
  480. type: Function,
  481. },
  482. onUploading: {
  483. type: Function,
  484. },
  485. requiredFieldOnly: {
  486. type: Boolean,
  487. },
  488. isShowAll: {
  489. type: Function,
  490. },
  491. interrupt: {
  492. type: Function,
  493. },
  494. },
  495. data() {
  496. return {
  497. list: [],
  498. focusLabel: "",
  499. unShowAll: false,
  500. showTagModal: false,
  501. tagValue: "",
  502. };
  503. },
  504. watch: {
  505. form: {
  506. handler: function (newVal) {
  507. if (newVal) {
  508. this.list = JSON.parse(JSON.stringify(newVal));
  509. setTimeout(() => {
  510. this.verify();
  511. }, 200);
  512. }
  513. },
  514. immediate: true,
  515. },
  516. unShowAll: function (newVal) {
  517. this.$emit("isShowAll", newVal);
  518. },
  519. },
  520. async created() {
  521. /* let list = [{
  522. key: "name",
  523. type: "text",
  524. label: "标题",
  525. isMust: true,//是否必填
  526. value: "",
  527. inputmode:"", //https://uniapp.dcloud.net.cn/component/input.html#type
  528. marginTop: 10,
  529. verify:[],
  530. }, {
  531. key: "Class",
  532. type: "customClass",
  533. label: "标题",
  534. isMust: false,//是否必填
  535. isMultipleChoice: true,//是否多选
  536. value: [],// 多选[] 单选 ""
  537. isMust: true,//是否必填
  538. list: await this.getCustomClass('picturespace'),
  539. marginTop: 10
  540. },{
  541. key: "attachmentids",
  542. type: "upload",
  543. label: "图片/视频",
  544. accept:"all",
  545. placeholder: "可上传多个视频或图片",
  546. ownertable: "temporary",
  547. ownerid: 999,
  548. usetype: 'default',
  549. allowUpload: true,
  550. allowDelete: true,
  551. value:[],
  552. marginTop: 10
  553. }, {
  554. key: "region",
  555. type: "region",
  556. label: "所在地区",
  557. isMust: true,//是否必填
  558. value: [],
  559. }, {
  560. key: "address",
  561. type: "textarea",
  562. label: "详细地址",
  563. isMust: true,//是否必填
  564. value: '',
  565. }, {
  566. key: "isdefault",
  567. type: "switch",
  568. label: "设为默认地址",
  569. isMust: false,//是否必填
  570. value: false,
  571. isNum: true,
  572. unBorBot: true
  573. }] */
  574. },
  575. methods: {
  576. delTag(tag, index) {
  577. let item = this.list[index];
  578. console.log(tag);
  579. item.value.splice(item.value.indexOf(tag), 1);
  580. this.$set(this.list[index], "value", item.value);
  581. },
  582. addTagSend(index) {
  583. let item = this.list[index];
  584. if (!item.errText) {
  585. item.value.push(this.tagValue);
  586. this.$set(this.list[index], "value", item.value);
  587. this.tagValue = "";
  588. this.showTagModal = false;
  589. }
  590. },
  591. toRoute(item, index) {
  592. let url = item.path;
  593. if (item.showValue.length) {
  594. let obj = JSON.stringify({
  595. value: item.value,
  596. showValue: item.showValue,
  597. });
  598. url +=
  599. (url.indexOf("?") == -1
  600. ? "?alreadySelecteds="
  601. : "&alreadySelecteds=") + obj;
  602. }
  603. uni.navigateTo({
  604. url,
  605. });
  606. this.$Http.routeSelected = function (selected) {
  607. this.$emit("interrupt", item, selected, index);
  608. delete this.$Http.routeSelected;
  609. }.bind(this);
  610. },
  611. onTagInput(e, index) {
  612. let item = this.list[index];
  613. item.errText = "";
  614. if (item.verify && item.verify.length && this.tagValue != "") {
  615. let err = item.verify.find(
  616. (r) => !new RegExp(r.reg).test(this.tagValue)
  617. );
  618. if (err) this.$set(this.list[index], "errText", err.errText);
  619. }
  620. this.verify();
  621. },
  622. butGetphonenumber(e, index) {
  623. if (e.detail.code) {
  624. this.$Http
  625. .basic({
  626. id: 20240520110702,
  627. content: {
  628. systemclient: getApp().globalData.systemclient,
  629. code: e.detail.code,
  630. },
  631. })
  632. .then((res) => {
  633. console.log("获取手机号", res);
  634. if (this.cutoff(res.msg)) return;
  635. this.$set(this.list[index], "value", res.data.phoneNumber);
  636. this.verify();
  637. });
  638. }
  639. },
  640. onInput(e, index) {
  641. let item = this.list[index];
  642. item.errText = "";
  643. this.$set(this.list[index], "value", e.detail.value);
  644. if (item.verify && item.verify.length && item.value != "") {
  645. let err = item.verify.find((r) => !new RegExp(r.reg).test(item.value));
  646. if (err) this.$set(this.list[index], "errText", err.errText);
  647. }
  648. this.verify();
  649. },
  650. setItem(index, item, back = false) {
  651. this.$set(this.list, index, item);
  652. this.verify();
  653. if (back) uni.navigateBack();
  654. },
  655. setValue(index, value, back = false) {
  656. this.$set(this.list[index], "value", value);
  657. this.verify();
  658. if (back) uni.navigateBack();
  659. },
  660. onClearInput(index) {
  661. let item = this.list[index];
  662. item.errText = "";
  663. this.$set(this.list[index], "value", "");
  664. this.verify();
  665. },
  666. switchChange(e, index) {
  667. this.$set(this.list[index], "value", e);
  668. this.verify();
  669. },
  670. changOptions(value, index) {
  671. let item = this.list[index];
  672. if (item.isMultipleChoice) {
  673. let i = -1;
  674. try {
  675. i = item.value.findIndex((v) => v == value);
  676. } catch (error) {}
  677. if (i == -1) {
  678. item.value.push(value);
  679. } else {
  680. item.value.splice(i, 1);
  681. }
  682. this.$set(this.list[index], "value", item.value);
  683. } else {
  684. this.$set(this.list[index], "value", value);
  685. }
  686. this.verify();
  687. },
  688. verify() {
  689. let list = this.list.filter((v) => v.isMust);
  690. let Uncomplete = false;
  691. if (list.length)
  692. Uncomplete = list.some((v) => {
  693. let res = false;
  694. if (v.type == "customClass") {
  695. if (v.isMultipleChoice) {
  696. res = v.value.length == 0;
  697. } else {
  698. res = v.value == "";
  699. }
  700. } else if (v.type == "upload") {
  701. res = v.value.length == 0;
  702. } else if (v.type == "text") {
  703. res = v.value == "";
  704. if (v.errText) res = true;
  705. } else if (v.type == "route") {
  706. res = v.showValue.length == 0;
  707. } else {
  708. res = v.value == "";
  709. }
  710. return res;
  711. });
  712. if (!Uncomplete)
  713. Uncomplete = this.list.filter((v) => !v.isMust).some((v) => v.errText);
  714. this.$emit("isUncomplete", Uncomplete);
  715. },
  716. previewImg(item) {
  717. viewImage(item.url);
  718. },
  719. uploadCallback(attachmentids, index) {
  720. let item = this.list[index];
  721. this.$Http
  722. .basic({
  723. classname: "system.attachment.Attachment",
  724. method: "createFileLink",
  725. content: {
  726. ownertable: item.ownertable,
  727. ownerid: item.ownerid,
  728. usetype: item.usetype,
  729. attachmentids,
  730. },
  731. })
  732. .then((res) => {
  733. console.log("绑定附件", res);
  734. if (this.cutoff(res.msg)) return;
  735. res.data = formattedFiles(res.data);
  736. item.value.push(res.data[0]);
  737. //临时文件
  738. if (res.data[0].ownertable == "temporary")
  739. try {
  740. item.temporarys.push(attachmentids[0]);
  741. } catch (error) {
  742. item.temporarys = [attachmentids[0]];
  743. }
  744. this.$set(this.list[index], "value", item.value);
  745. this.verify();
  746. });
  747. },
  748. deleteFiles() {
  749. this.list.forEach((v) => {
  750. if (v.type == "upload") {
  751. let linksids = v.value
  752. .filter((v) => v.ownertable == "temporary")
  753. .map((v) => v.linksid);
  754. if (linksids.length)
  755. this.$Http
  756. .basic({
  757. classname: "system.attachment.Attachment",
  758. method: "deleteFileLink",
  759. content: {
  760. linksids,
  761. },
  762. })
  763. .then((res) => {
  764. console.log("处理删除附件", res);
  765. if (this.cutoff(res.msg)) return;
  766. });
  767. }
  768. });
  769. },
  770. onUploadLoading(e, index) {
  771. this.$set(this.list[index], "loading", e);
  772. this.$emit("onUploading", e);
  773. },
  774. groupChange(e, index) {
  775. this.$set(this.list[index], "loading", e);
  776. this.verify();
  777. },
  778. selectRegion({ detail }, index) {
  779. this.$set(this.list[index], "value", detail.value);
  780. this.verify();
  781. },
  782. deleteFile(flie, index) {
  783. let item = this.list[index];
  784. item.value = item.value.filter(
  785. (v) => v.attachmentid != flie.attachmentid
  786. );
  787. //临时文件
  788. if (flie.ownertable == "temporary") {
  789. item.temporarys = item.temporarys.filter((v) => v != flie.attachmentid);
  790. this.$Http
  791. .basic({
  792. classname: "system.attachment.Attachment",
  793. method: "deleteFileLink",
  794. content: {
  795. linksids: [flie.linksid],
  796. },
  797. })
  798. .then((res) => {
  799. console.log("处理删除附件", res);
  800. if (this.cutoff(res.msg)) return;
  801. });
  802. } else {
  803. try {
  804. item.linksids.push(flie.linksid);
  805. } catch (error) {
  806. item.linksids = [flie.linksid];
  807. }
  808. }
  809. this.$set(this.list[index], "value", item.value);
  810. this.verify();
  811. },
  812. submit() {
  813. return new Promise((resolve, reject) => {
  814. let res = {};
  815. this.list.forEach((v) => {
  816. if (v.type == "upload") {
  817. res.files = {
  818. temporarys: [],
  819. linksids: [],
  820. };
  821. try {
  822. res.files.temporarys = v.temporarys || [];
  823. } catch (error) {}
  824. try {
  825. res.files.linksids = v.linksids || [];
  826. } catch (error) {}
  827. } else if (v.type == "region") {
  828. if (v.value.length) {
  829. res.province = v.value[0];
  830. res.city = v.value[1];
  831. res.county = v.value[2];
  832. } else {
  833. res.province = "";
  834. res.city = "";
  835. res.county = "";
  836. }
  837. } else if (v.type == "switch") {
  838. if (v.isNum) {
  839. res[v.key] = v.value ? 1 : 0;
  840. } else {
  841. res[v.key] = v.value;
  842. }
  843. } else if (v.type == "route") {
  844. if (v.isRadio) {
  845. const routeValue =
  846. typeof v.value.length == "number"
  847. ? v.value.length
  848. ? v.value[0]
  849. : ""
  850. : v.value || {};
  851. if (v.keys) {
  852. v.keys.forEach((e) => {
  853. res[e] = routeValue ? routeValue[e] || "" : "";
  854. });
  855. } else {
  856. res[v.key] = {
  857. name: v.showValue[0] || "",
  858. value: routeValue,
  859. };
  860. }
  861. } else {
  862. res[v.key] = {
  863. name: v.showValue || [],
  864. value: v.value || [],
  865. };
  866. }
  867. } else {
  868. try {
  869. res[v.key] = v.value.trim();
  870. } catch (error) {
  871. res[v.key] = v.value;
  872. }
  873. }
  874. });
  875. resolve(res);
  876. });
  877. },
  878. },
  879. };
  880. </script>
  881. <style lang="scss">
  882. .requiredFieldOnly-head {
  883. display: flex;
  884. align-items: center;
  885. justify-content: space-between;
  886. width: 100vw;
  887. height: 45px;
  888. background: #f7f7f7;
  889. padding: 0 10px;
  890. box-sizing: border-box;
  891. .label {
  892. font-family: PingFang SC, PingFang SC;
  893. font-weight: bold;
  894. font-size: 15px;
  895. color: #333333;
  896. line-height: 22px;
  897. }
  898. .content {
  899. display: flex;
  900. align-items: center;
  901. font-family: PingFang SC, PingFang SC;
  902. font-size: 14px;
  903. color: #999999;
  904. }
  905. }
  906. .borBot {
  907. border-bottom: 1px #dddddd solid;
  908. }
  909. .custom-class-box {
  910. width: 100%;
  911. background: #fff;
  912. padding: 15px 0 15px 10px;
  913. box-sizing: border-box;
  914. .head {
  915. width: 355px;
  916. height: 20px;
  917. display: flex;
  918. justify-content: space-between;
  919. align-items: flex-end;
  920. .label {
  921. font-size: 14px;
  922. color: #333333;
  923. line-height: 20px;
  924. }
  925. .state {
  926. font-family: Source Han Sans SC, Source Han Sans SC;
  927. font-size: 12px;
  928. color: #999999;
  929. }
  930. }
  931. .options {
  932. display: flex;
  933. flex-wrap: wrap;
  934. .option {
  935. padding: 6px 10px;
  936. text-align: center;
  937. min-width: 81px;
  938. font-family: PingFang SC, PingFang SC;
  939. font-size: 14px;
  940. color: #333333;
  941. border-radius: 5px;
  942. background: #f2f2f2;
  943. margin-top: 10px;
  944. margin-right: 10px;
  945. box-sizing: border-box;
  946. }
  947. .active {
  948. background: #c30d23;
  949. color: #fff;
  950. }
  951. }
  952. .content {
  953. .file-box {
  954. position: relative;
  955. width: 355px;
  956. height: 240px;
  957. margin-top: 10px;
  958. .video,
  959. .image {
  960. width: 355px;
  961. height: 240px;
  962. border-radius: 5px;
  963. }
  964. .delete {
  965. position: absolute;
  966. width: 30px;
  967. top: 0;
  968. right: 0;
  969. z-index: 1;
  970. }
  971. }
  972. .upload-box {
  973. display: flex;
  974. justify-content: center;
  975. align-items: center;
  976. width: 355px;
  977. height: 45px;
  978. background: #ffffff;
  979. border-radius: 5px;
  980. border: 1px dashed #c30d23;
  981. font-family: Source Han Sans SC, Source Han Sans SC;
  982. font-size: 14px;
  983. color: #c30d23;
  984. margin-top: 10px;
  985. }
  986. }
  987. }
  988. .textarea-box {
  989. width: 100%;
  990. .textarea {
  991. width: 355px;
  992. height: 160px;
  993. padding: 15px 10px;
  994. box-sizing: border-box;
  995. margin: 0 auto;
  996. }
  997. }
  998. .textarea-box2 {
  999. width: 100%;
  1000. display: flex;
  1001. flex-direction: column;
  1002. background: #ffffff;
  1003. padding: 15px 0 15px 10px;
  1004. .label {
  1005. width: 100px;
  1006. margin-right: 10px;
  1007. line-height: 20px;
  1008. font-family: Source Han Sans SC, Source Han Sans SC;
  1009. font-size: 14px;
  1010. color: #666666;
  1011. flex-shrink: 0;
  1012. .must {
  1013. color: #e3041f;
  1014. margin-right: 5px;
  1015. }
  1016. }
  1017. .textarea {
  1018. width: 355px;
  1019. height: 160px;
  1020. padding: 15px 10px;
  1021. box-sizing: border-box;
  1022. margin: 0 auto;
  1023. }
  1024. }
  1025. .input-box {
  1026. width: 100vw;
  1027. background: #fff;
  1028. box-sizing: border-box;
  1029. padding-left: 10px;
  1030. .box {
  1031. display: flex;
  1032. width: 100%;
  1033. min-height: 54.4px;
  1034. padding: 15px 0;
  1035. box-sizing: border-box;
  1036. align-items: center;
  1037. }
  1038. .label {
  1039. width: 100px;
  1040. margin-right: 10px;
  1041. line-height: 20px;
  1042. font-family: Source Han Sans SC, Source Han Sans SC;
  1043. font-size: 14px;
  1044. color: #666666;
  1045. flex-shrink: 0;
  1046. .must {
  1047. color: #e3041f;
  1048. margin-right: 5px;
  1049. }
  1050. }
  1051. .content-box {
  1052. padding-right: 10px;
  1053. .content {
  1054. flex: 1;
  1055. display: flex;
  1056. align-items: center;
  1057. box-sizing: border-box;
  1058. .icon {
  1059. padding: 5px;
  1060. }
  1061. }
  1062. .err-text {
  1063. font-size: 12px;
  1064. color: #e3041f;
  1065. margin-bottom: -12px;
  1066. .icon {
  1067. margin-right: 2px;
  1068. }
  1069. }
  1070. }
  1071. }
  1072. .region {
  1073. width: 100vw;
  1074. background: #fff;
  1075. box-sizing: border-box;
  1076. padding: 15px 0 0 10px;
  1077. .box {
  1078. display: flex;
  1079. padding-bottom: 15px;
  1080. padding-right: 10px;
  1081. box-sizing: border-box;
  1082. .label {
  1083. width: 100px;
  1084. margin-right: 10px;
  1085. line-height: 20px;
  1086. font-family: Source Han Sans SC, Source Han Sans SC;
  1087. font-size: 14px;
  1088. color: #666666;
  1089. flex-shrink: 0;
  1090. .must {
  1091. color: #e3041f;
  1092. margin-right: 5px;
  1093. }
  1094. }
  1095. .content-box {
  1096. flex: 1;
  1097. display: flex;
  1098. align-items: center;
  1099. justify-content: space-between;
  1100. height: 20px;
  1101. line-height: 20px;
  1102. .placeholder {
  1103. font-family: Source Han Sans SC, Source Han Sans SC;
  1104. font-size: 14px;
  1105. color: #bbbbbb;
  1106. }
  1107. }
  1108. .content-box2 {
  1109. flex: 1;
  1110. display: flex;
  1111. align-items: center;
  1112. justify-content: space-between;
  1113. line-height: 20px;
  1114. .placeholder {
  1115. font-family: Source Han Sans SC, Source Han Sans SC;
  1116. font-size: 14px;
  1117. color: #bbbbbb;
  1118. }
  1119. }
  1120. }
  1121. }
  1122. .tag-box {
  1123. .label {
  1124. width: 100px;
  1125. margin-right: 10px;
  1126. line-height: 20px;
  1127. font-family: Source Han Sans SC, Source Han Sans SC;
  1128. font-size: 14px;
  1129. color: #666666;
  1130. flex-shrink: 0;
  1131. .must {
  1132. color: #e3041f;
  1133. margin-right: 5px;
  1134. }
  1135. }
  1136. .tag-list {
  1137. display: flex;
  1138. align-content: center;
  1139. align-items: center;
  1140. flex-wrap: wrap;
  1141. font-family: PingFang SC, PingFang SC;
  1142. margin-top: 10px;
  1143. .err-text {
  1144. font-size: 12px;
  1145. color: #e3041f;
  1146. margin-bottom: -12px;
  1147. .icon {
  1148. margin-right: 2px;
  1149. }
  1150. }
  1151. .tag {
  1152. padding: 6px 10px;
  1153. background: #f2f2f2;
  1154. border-radius: 5px 5px 5px 5px;
  1155. margin-right: 10px;
  1156. margin-bottom: 10px;
  1157. font-weight: 400;
  1158. font-size: 14px;
  1159. color: #333333;
  1160. display: flex;
  1161. align-items: center;
  1162. align-content: center;
  1163. text-align: center;
  1164. &:last-child {
  1165. margin-right: 0 !important;
  1166. }
  1167. .del {
  1168. margin-left: 10px;
  1169. padding: 2px;
  1170. }
  1171. }
  1172. .add-tag {
  1173. border-radius: 5px 5px 5px 5px;
  1174. border: 1px dashed #c30d23;
  1175. padding: 6px 20px;
  1176. color: #c30d23;
  1177. font-weight: 400;
  1178. margin-bottom: 10px;
  1179. font-size: 14px;
  1180. }
  1181. }
  1182. }
  1183. </style>