GenerateFormItem.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457
  1. <template>
  2. <div
  3. v-if="element.type === 'grid'"
  4. grid="~ cols-24"
  5. :style="`gap: ${element.options.gutter}px; align-items: ${element.options.align};`"
  6. >
  7. <div
  8. v-for="(col, colIndex) of element.columns"
  9. :key="colIndex"
  10. :style="`grid-column: span ${col.span}`"
  11. >
  12. <GenerateFormItem
  13. v-for="colItem of col.list"
  14. :key="colItem.key"
  15. :request="request"
  16. :model="model"
  17. :updated-model="updatedModel"
  18. :element="colItem"
  19. :config="config"
  20. :disabled="disabled"
  21. :widgetFormData="element.columns"
  22. @updateWidgetForm="updateWidgetForm"
  23. />
  24. </div>
  25. </div>
  26. <el-table
  27. v-else-if="element.type === 'table'"
  28. border
  29. class="mb-4.5"
  30. :data="element.options.defaultValue"
  31. >
  32. <el-table-column
  33. v-for="i in element.columns"
  34. :key="i.prop"
  35. :align="element.options.align"
  36. v-bind="i"
  37. />
  38. </el-table>
  39. <el-divider
  40. v-else-if="element.type === 'divider'"
  41. :data="element.options.defaultValue"
  42. content-position="left"
  43. >
  44. {{ element.label }}
  45. </el-divider>
  46. <el-form-item
  47. v-else-if="element"
  48. :key="element.key"
  49. :label="element.label"
  50. :prop="element.model"
  51. :style="
  52. element.type === 'download' ? 'display:inline-flex;margin-right:40px' : ''
  53. "
  54. :label-width="element.labelWidth"
  55. >
  56. <template v-if="element.type === 'input'">
  57. <el-input
  58. v-model.trim="data"
  59. :style="{ width: element.options.width }"
  60. :placeholder="element.options.placeholder"
  61. :maxlength="parseInt(element.options.maxlength)"
  62. :clearable="element.options.clearable"
  63. :readonly="element.options.readonly"
  64. :disabled="disabled || element.options.disabled"
  65. >
  66. <template v-if="element.options.prefix" #prefix>
  67. {{
  68. element.options.prefix
  69. }}
  70. </template>
  71. <template v-if="element.options.suffix" #suffix>
  72. {{
  73. element.options.suffix
  74. }}
  75. </template>
  76. <template v-if="element.options.prepend" #prepend>
  77. {{
  78. element.options.prepend
  79. }}
  80. </template>
  81. <template v-if="element.options.append" #append>
  82. {{
  83. element.options.append
  84. }}
  85. </template>
  86. </el-input>
  87. </template>
  88. <template v-if="element.type === 'password'">
  89. <el-input
  90. v-model.trim="data"
  91. :style="{ width: element.options.width }"
  92. :placeholder="element.options.placeholder"
  93. :maxlength="parseInt(element.options.maxlength)"
  94. :clearable="element.options.clearable"
  95. :disabled="disabled || element.options.disabled"
  96. :readonly="element.options.readonly"
  97. :show-password="element.options.showPassword"
  98. >
  99. <template v-if="element.options.prefix" #prefix>
  100. {{
  101. element.options.prefix
  102. }}
  103. </template>
  104. <template v-if="element.options.suffix" #suffix>
  105. {{
  106. element.options.suffix
  107. }}
  108. </template>
  109. <template v-if="element.options.prepend" #prepend>
  110. {{
  111. element.options.prepend
  112. }}
  113. </template>
  114. <template v-if="element.options.append" #append>
  115. {{
  116. element.options.append
  117. }}
  118. </template>
  119. </el-input>
  120. </template>
  121. <template v-if="element.type === 'textarea'">
  122. <el-input
  123. v-model.trim="data"
  124. type="textarea"
  125. resize="none"
  126. :rows="element.options.rows"
  127. :style="{ width: element.options.width }"
  128. :placeholder="element.options.placeholder"
  129. :maxlength="parseInt(element.options.maxlength)"
  130. :show-word-limit="element.options.showWordLimit"
  131. :autosize="element.options.autosize"
  132. :clearable="element.options.clearable"
  133. :readonly="element.options.readonly"
  134. :disabled="disabled || element.options.disabled"
  135. />
  136. </template>
  137. <template v-if="element.type === 'number'">
  138. <el-input-number
  139. v-model="data"
  140. :style="{ width: element.options.width }"
  141. :max="element.options.max"
  142. :min="element.options.min"
  143. :disabled="disabled || element.options.disabled"
  144. controls-position="right"
  145. />
  146. </template>
  147. <template v-if="element.type === 'radio'">
  148. <el-radio-group
  149. v-model="data"
  150. :style="{ width: element.options.width }"
  151. :disabled="disabled || element.options.disabled"
  152. >
  153. <el-radio
  154. v-for="item of element.options.remote
  155. ? element.options.remoteOptions
  156. : element.options.options"
  157. :key="item.value"
  158. :label="item.value"
  159. :style="{
  160. display: element.options.inline ? 'inline-block' : 'block'
  161. }"
  162. >
  163. {{ element.options.showLabel ? item.label : item.value }}
  164. </el-radio>
  165. </el-radio-group>
  166. </template>
  167. <template v-if="element.type === 'checkbox'">
  168. <el-checkbox-group
  169. v-model="data"
  170. :style="{ width: element.options.width }"
  171. :disabled="disabled || element.options.disabled"
  172. >
  173. <el-checkbox
  174. v-for="item of element.options.remote
  175. ? element.options.remoteOptions
  176. : element.options.options"
  177. :key="item.value"
  178. :label="item.value"
  179. :style="{
  180. display: element.options.inline ? 'inline-block' : 'block'
  181. }"
  182. >
  183. {{ element.options.showLabel ? item.label : item.value }}
  184. </el-checkbox>
  185. </el-checkbox-group>
  186. </template>
  187. <template v-if="element.type === 'time'">
  188. <el-config-provider :locale="zhCn">
  189. <el-time-picker
  190. v-model="data"
  191. :placeholder="element.options.placeholder"
  192. :readonly="element.options.readonly"
  193. :editable="element.options.editable"
  194. :clearable="element.options.clearable"
  195. :format="element.options.format"
  196. :disabled="disabled || element.options.disabled"
  197. :style="{ width: element.options.width }"
  198. />
  199. </el-config-provider>
  200. </template>
  201. <template v-if="element.type === 'date'">
  202. <el-config-provider :locale="zhCn">
  203. <el-date-picker
  204. v-model="data"
  205. :placeholder="element.options.placeholder"
  206. :readonly="element.options.readonly"
  207. :editable="element.options.editable"
  208. :clearable="element.options.clearable"
  209. :format="element.options.format"
  210. :disabled="disabled || element.options.disabled"
  211. :style="{ width: element.options.width }"
  212. />
  213. </el-config-provider>
  214. </template>
  215. <template v-if="element.type === 'rate'">
  216. <el-rate
  217. v-model="data"
  218. :max="element.options.max"
  219. :allow-half="element.options.allowHalf"
  220. :disabled="disabled || element.options.disabled"
  221. />
  222. </template>
  223. <template v-if="element.type === 'select'">
  224. <template v-if="userInfo.userNameNeedTranslate == 1 && element.options.remoteFunc.indexOf('getSimpleActiveUserListNew') > -1">
  225. <personnelSearch
  226. v-model="data"
  227. :multiple="element.options.multiple"
  228. :placeholder="element.options.placeholder"
  229. :clearable="element.options.clearable"
  230. :filterable="element.options.filterable"
  231. :disabled="disabled || element.options.disabled"
  232. :url="element.options.remoteFunc"
  233. :size="config.size"
  234. :options="[]"
  235. :style="{ width: element.options.width }"
  236. @change="(value: any) => specializedHandleSelect(value, element)"
  237. >
  238. </personnelSearch>
  239. </template>
  240. <template v-else>
  241. <el-select
  242. v-model="data"
  243. :multiple="element.options.multiple"
  244. :placeholder="element.options.placeholder"
  245. :clearable="element.options.clearable"
  246. :filterable="element.options.filterable"
  247. :disabled="disabled || element.options.disabled"
  248. :style="{ width: element.options.width }"
  249. @change="(value: any) => specializedHandleSelect(value, element)"
  250. >
  251. <el-option
  252. v-for="item of element.options.remote
  253. ? element.options.remoteOptions
  254. : element.options.options"
  255. :key="item.value"
  256. :value="item.value"
  257. :label="element.options.showLabel ? item.label : item.value"
  258. />
  259. </el-select>
  260. </template>
  261. </template>
  262. <template v-if="element.type === 'switch'">
  263. <el-switch
  264. v-model="data"
  265. :active-text="element.options.activeText"
  266. :inactive-text="element.options.inactiveText"
  267. :disabled="disabled || element.options.disabled"
  268. />
  269. </template>
  270. <template v-if="element.type === 'slider'">
  271. <el-slider
  272. v-model="data"
  273. :min="element.options.min"
  274. :max="element.options.max"
  275. :step="element.options.step"
  276. :range="element.options.range"
  277. :disabled="disabled || element.options.disabled"
  278. :style="{ width: element.options.width }"
  279. />
  280. </template>
  281. <template v-if="element.type == 'text'">
  282. <span>{{ element.options.defaultValue }}</span>
  283. </template>
  284. <template v-if="element.type === 'img-upload'">
  285. <el-upload
  286. :name="element.options.file"
  287. :action="element.options.action"
  288. :accept="element.options.accept"
  289. :list-type="element.options.listType"
  290. :multiple="element.options.multiple"
  291. :limit="element.options.limit"
  292. :disabled="disabled || element.options.disabled"
  293. :on-success="handleUploadSuccess"
  294. >
  295. <template v-if="element.options.listType === 'picture-card'">
  296. <el-image
  297. v-if="element.options.defaultValue?.length"
  298. style=" width: 100%;height: 100%;"
  299. :preview-src-list="[
  300. '/api/sys/common/static/' + element.options.defaultValue
  301. ]"
  302. :src="'/api/sys/common/static/' + element.options.defaultValue"
  303. />
  304. <i v-else class="custom:insert" />
  305. </template>
  306. <el-button v-else>
  307. <i class="custom:img-upload mr-2" />点击上传
  308. </el-button>
  309. </el-upload>
  310. </template>
  311. <template v-if="element.type === 'download'" #label="{ label }">
  312. <a
  313. :href="`/api/sys/common/static/${element.options.defaultValue}?inline=1`"
  314. style="color: #606266;"
  315. target="_blank"
  316. >
  317. {{ label }}
  318. </a>
  319. </template>
  320. <template v-if="element.type === 'download'">
  321. <el-button
  322. style="margin-top: -4px;"
  323. type="text"
  324. @click="download(element.options.defaultValue, element.label)"
  325. >
  326. 下载
  327. </el-button>
  328. </template>
  329. <template v-if="element.type === 'cascader'">
  330. <el-cascader
  331. v-model="data"
  332. :options="element.options.remoteOptions"
  333. :placeholder="element.options.placeholder"
  334. :filterable="element.options.filterable"
  335. :clearable="element.options.clearable"
  336. :disabled="disabled || element.options.disabled"
  337. :style="{ width: element.options.width }"
  338. />
  339. </template>
  340. </el-form-item>
  341. </template>
  342. <script lang="ts" setup>
  343. import type { WidgetForm } from '@/config'
  344. import zhCn from "element-plus/es/locale/lang/zh-cn";
  345. import personnelSearch from '@/components/personnelSearch.vue';
  346. const { userInfo = {} } = JSON.parse(sessionStorage.getItem('storeInfo') || '{}')
  347. const props = defineProps<{
  348. config: WidgetForm['config']
  349. element: any
  350. model: any
  351. updatedModel: any
  352. disabled: boolean
  353. request?: Function
  354. widgetFormData?: any
  355. }>()
  356. const originData = props.model[props.element.model]
  357. const data = computed({
  358. get: () => props.model[props.element.model],
  359. set: (val) => {
  360. // eslint-disable-next-line vue/no-mutating-props
  361. props.model[props.element.model] = val
  362. if (JSON.stringify(originData) === JSON.stringify(val)) {
  363. Reflect.deleteProperty(props.updatedModel, props.element.model)
  364. }
  365. else {
  366. // eslint-disable-next-line vue/no-mutating-props
  367. props.updatedModel[props.element.model] = val
  368. }
  369. },
  370. })
  371. const handleUploadSuccess = (_res: any, _file: any, fileList: any[]) => {
  372. data.value = fileList
  373. }
  374. async function download(defaultValue: string, label: string) {
  375. const a = document.createElement('a')
  376. if (!props.request) return
  377. a.href = await props
  378. .request({
  379. url: `/sys/common/static/${defaultValue}`,
  380. responseType: 'blob',
  381. })
  382. .then((i: any) => {
  383. if (i.size === 0) return ''
  384. return URL.createObjectURL(i)
  385. })
  386. a.download = `${label}.${defaultValue.split('.')[1]}`
  387. a.click()
  388. }
  389. const emits = defineEmits(['updateWidgetForm'])
  390. const specializedHandleSelect = (val: any, element: any) => {
  391. const field = element.model
  392. if(field == 'customerId') {
  393. // console.log(props, '<===== props')
  394. let list = JSON.parse(JSON.stringify(props.widgetFormData))
  395. for(var i in list) {
  396. if(list[i].list[0].model == 'contactsId') {
  397. let item = list[i].list[0]
  398. const token: any = sessionStorage.getItem('token')
  399. // fetch(item.options.remoteFunc, {
  400. fetch(`${item.options.remoteFunc}?customerId=${val}`, {
  401. headers: {
  402. "Content-type": " application/x-www-form-urlencoded; charset=UTF-8",
  403. "Token": token
  404. }
  405. })
  406. .then(resp => resp.json())
  407. .then((json) => {
  408. const res = json.data
  409. if (res instanceof Array) {
  410. item.options.remoteOptions = res.map(data => ({
  411. label: data[item.options.props.label],
  412. value: data[item.options.props.value],
  413. children: data[item.options.props.children],
  414. }))
  415. }
  416. list[i].list[0].options = {...list[i].list[0].options, disabled: false, defaultValue: ''}
  417. })
  418. }
  419. }
  420. setTimeout(() => {
  421. console.log('开始执行')
  422. updateWidgetForm(list)
  423. }, 100)
  424. }
  425. }
  426. const updateWidgetForm = (list: any) => {
  427. emits('updateWidgetForm', list)
  428. }
  429. </script>
  430. <style scoped>
  431. :deep(.el-upload--picture-card) {
  432. width: 134px;
  433. height: 134px;
  434. }
  435. </style>