WidgetFormItem.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. <script lang="ts" setup>
  2. import Draggable from 'vuedraggable'
  3. import { cloneWidget } from '@/components/ComponentGroup.vue'
  4. import personnelSearch from '@/components/personnelSearch.vue';
  5. import type { WidgetForm } from '@/config'
  6. const { element, index, list, ...props } = defineProps<{
  7. list: any
  8. element: any
  9. index: number
  10. selectWidget: any
  11. configurationItems: WidgetForm['config']
  12. }>()
  13. defineEmits(['itemClick', 'delete', 'update:selectWidget'])
  14. let selectWidget = $(useVModel(props, 'selectWidget'))
  15. const { userInfo = {} } = JSON.parse(sessionStorage.getItem('storeInfo') || '{}')
  16. const handleCopyClick = () => {
  17. list.splice(index + 1, 0, cloneWidget(list[index]))
  18. selectWidget = list[index + 1]
  19. }
  20. const handleDeleteClick = () => {
  21. list.splice(index, 1)
  22. selectWidget = list[list.length === index ? (index - 1) : index]
  23. }
  24. </script>
  25. <template>
  26. <div
  27. class="widget-view"
  28. :class="{ active: selectWidget?.key === element.key ,col:element.type === 'grid'}"
  29. :style="element.type === 'grid'?`gap: ${element.options.gutter}px; align-items: ${element.options.align};`:''"
  30. @click.stop="selectWidget=element"
  31. >
  32. <template v-if="element.type === 'grid'">
  33. <Draggable
  34. v-for="(col, key) of element.columns"
  35. :key="key"
  36. class="bg-white min-h-12 border border-dashed border-gray-300"
  37. :style="`grid-column: span ${col.span}`"
  38. item-key="key"
  39. handle="[cursor-move]"
  40. :animation="200"
  41. group="form-design"
  42. :no-transition-on-drag="true"
  43. :list="col.list"
  44. @add="selectWidget=col.list[$event.newIndex]"
  45. >
  46. <template #item="{ element: colElement, index: colIndex }">
  47. <WidgetFormItem
  48. v-model:selectWidget="selectWidget"
  49. :element="colElement"
  50. :list="col.list"
  51. :index="colIndex"
  52. :configurationItems="configurationItems"
  53. />
  54. </template>
  55. </Draggable>
  56. </template>
  57. <el-table
  58. v-else-if="element.type === 'table'"
  59. class="w-0 flex-1"
  60. border
  61. :data="element.options.defaultValue"
  62. >
  63. <el-table-column
  64. v-for="i in element.columns"
  65. :key="i.prop"
  66. :header-align="element.options.align"
  67. :align="element.options.align"
  68. v-bind="i"
  69. />
  70. </el-table>
  71. <el-divider v-else-if="element.type === 'divider'" class="pb-0" :data="element.options.defaultValue" content-position="left">
  72. {{ element.label }}
  73. </el-divider>
  74. <el-form-item
  75. v-else-if="element"
  76. :key="element.key"
  77. :label="element.label"
  78. :label-width="element.labelWidth"
  79. :rules="element.options.rules"
  80. >
  81. <template v-if="element.type === 'input'">
  82. <el-input
  83. readonly
  84. :model-value="element.options.defaultValue"
  85. :style="{ width: element.options.width }"
  86. :placeholder="element.options.placeholder"
  87. :maxlength="parseInt(element.options.maxlength)"
  88. :clearable="element.options.clearable"
  89. :disabled="element.options.disabled"
  90. >
  91. <template v-if="element.options.prefix" #prefix>
  92. {{ element.options.prefix }}
  93. </template>
  94. <template v-if="element.options.suffix" #suffix>
  95. {{ element.options.suffix }}
  96. </template>
  97. <template v-if="element.options.prepend" #prepend>
  98. {{ element.options.prepend }}
  99. </template>
  100. <template v-if="element.options.append" #append>
  101. {{ element.options.append }}
  102. </template>
  103. </el-input>
  104. </template>
  105. <template v-if="element.type === 'password'">
  106. <el-input
  107. readonly
  108. :model-value="element.options.defaultValue"
  109. :style="{ width: element.options.width }"
  110. :placeholder="element.options.placeholder"
  111. :maxlength="parseInt(element.options.maxlength)"
  112. :clearable="element.options.clearable"
  113. :disabled="element.options.disabled"
  114. :show-password="element.options.showPassword"
  115. >
  116. <template v-if="element.options.prefix" #prefix>
  117. {{ element.options.prefix }}
  118. </template>
  119. <template v-if="element.options.suffix" #suffix>
  120. {{ element.options.suffix }}
  121. </template>
  122. <template v-if="element.options.prepend" #prepend>
  123. {{ element.options.prepend }}
  124. </template>
  125. <template v-if="element.options.append" #append>
  126. {{ element.options.append }}
  127. </template>
  128. </el-input>
  129. </template>
  130. <template v-if="element.type === 'textarea'">
  131. <el-input
  132. type="textarea"
  133. resize="none"
  134. readonly
  135. :rows="element.options.rows"
  136. :model-value="element.options.defaultValue"
  137. :style="{ width: element.options.width }"
  138. :placeholder="element.options.placeholder"
  139. :maxlength="parseInt(element.options.maxlength)"
  140. :show-word-limit="element.options.showWordLimit"
  141. :autosize="element.options.autosize"
  142. :clearable="element.options.clearable"
  143. :disabled="element.options.disabled"
  144. />
  145. </template>
  146. <template v-if="element.type === 'number'">
  147. <el-input-number
  148. :model-value="element.options.defaultValue"
  149. :style="{ width: element.options.width }"
  150. :max="element.options.max"
  151. :min="element.options.min"
  152. :disabled="element.options.disabled"
  153. controls-position="right"
  154. />
  155. </template>
  156. <template v-if="element.type === 'radio'">
  157. <el-radio-group
  158. :model-value="element.options.defaultValue"
  159. :style="{ width: element.options.width }"
  160. :disabled="element.options.disabled"
  161. >
  162. <el-radio
  163. v-for="item of element.options.options"
  164. :key="item.value"
  165. :label="item.value"
  166. :style="{
  167. display: element.options.inline ? 'inline-block' : 'block'
  168. }"
  169. >
  170. {{ element.options.showLabel ? item.label : item.value }}
  171. </el-radio>
  172. </el-radio-group>
  173. </template>
  174. <template v-if="element.type === 'checkbox'">
  175. <el-checkbox-group
  176. :model-value="element.options.defaultValue"
  177. :style="{ width: element.options.width }"
  178. :disabled="element.options.disabled"
  179. >
  180. <el-checkbox
  181. v-for="item of element.options.options"
  182. :key="item.value"
  183. :label="item.value"
  184. :style="{
  185. display: element.options.inline ? 'inline-block' : 'block'
  186. }"
  187. >
  188. {{ element.options.showLabel ? item.label : item.value }}
  189. </el-checkbox>
  190. </el-checkbox-group>
  191. </template>
  192. <template v-if="element.type === 'time'">
  193. <el-time-picker
  194. :model-value="element.options.defaultValue"
  195. :placeholder="element.options.placeholder"
  196. :readonly="element.options.readonly"
  197. :editable="element.options.editable"
  198. :clearable="element.options.clearable"
  199. :format="element.options.format"
  200. :disabled="element.options.disabled"
  201. :style="{ width: element.options.width }"
  202. />
  203. </template>
  204. <template v-if="element.type === 'date'">
  205. <el-date-picker
  206. :model-value="element.options.defaultValue"
  207. :placeholder="element.options.placeholder"
  208. :readonly="element.options.readonly"
  209. :editable="element.options.editable"
  210. :clearable="element.options.clearable"
  211. :format="element.options.format"
  212. :disabled="element.options.disabled"
  213. :style="{ width: element.options.width }"
  214. />
  215. </template>
  216. <template v-if="element.type === 'rate'">
  217. <el-rate
  218. :model-value="element.options.defaultValue"
  219. :max="element.options.max"
  220. :allow-half="element.options.allowHalf"
  221. :disabled="element.options.disabled"
  222. />
  223. </template>
  224. <template v-if="element.type === 'select'">
  225. <template v-if="userInfo.userNameNeedTranslate == 1 && element.options.remoteFunc.indexOf('getSimpleActiveUserListNew') > -1">
  226. <personnelSearch
  227. :model-value="element.options.defaultValue"
  228. :multiple="element.options.multiple"
  229. :placeholder="element.options.placeholder"
  230. :clearable="element.options.clearable"
  231. :filterable="element.options.filterable"
  232. :disabled="element.options.disabled"
  233. :url="element.options.remoteFunc"
  234. :size="configurationItems.size"
  235. :options="[]"
  236. :style="{ width: element.options.width }"
  237. >
  238. </personnelSearch>
  239. </template>
  240. <template v-else>
  241. <el-select
  242. :model-value="element.options.defaultValue"
  243. :multiple="element.options.multiple"
  244. :placeholder="element.options.placeholder"
  245. :clearable="element.options.clearable"
  246. :filterable="element.options.filterable"
  247. :disabled="element.options.disabled"
  248. :style="{ width: element.options.width }"
  249. >
  250. <el-option
  251. v-for="item of element.options.options"
  252. :key="item.value"
  253. :value="item.value"
  254. :label="element.options.showLabel ? item.label : item.value"
  255. />
  256. </el-select>
  257. </template>
  258. </template>
  259. <template v-if="element.type === 'switch'">
  260. <el-switch
  261. :model-value="element.options.defaultValue"
  262. :active-text="element.options.activeText"
  263. :inactive-text="element.options.inactiveText"
  264. :disabled="element.options.disabled"
  265. />
  266. </template>
  267. <template v-if="element.type === 'slider'">
  268. <el-slider
  269. :model-value="element.options.defaultValue"
  270. :min="element.options.min"
  271. :max="element.options.max"
  272. :step="element.options.step"
  273. :range="element.options.range"
  274. :disabled="element.options.disabled"
  275. :style="{ width: element.options.width }"
  276. />
  277. </template>
  278. <template v-if="element.type == 'text'">
  279. <span>{{ element.options.defaultValue }}</span>
  280. </template>
  281. <template v-if="element.type === 'img-upload'">
  282. <el-upload
  283. :name="element.options.file"
  284. :action="element.options.action"
  285. :accept="element.options.accept"
  286. :list-type="element.options.listType"
  287. :multiple="element.options.multiple"
  288. :limit="element.options.limit"
  289. :disabled="element.options.disabled"
  290. >
  291. <template v-if="element.options.listType === 'picture-card'">
  292. <el-image
  293. v-if="element.options.defaultValue?.length"
  294. style="width: 100%; height: 100%;"
  295. :preview-src-list="[
  296. '/api/sys/common/static/' + element.options.defaultValue
  297. ]"
  298. :src="'/api/sys/common/static/' + element.options.defaultValue"
  299. />
  300. <i v-else class="custom:insert" />
  301. </template>
  302. <el-button v-else>
  303. <i icon-class="custom:img-upload" style="margin-right: 10px;" />
  304. 点击上传
  305. </el-button>
  306. </el-upload>
  307. </template>
  308. <template v-if="element.type === 'download'">
  309. <el-button type="text" style="margin-top: -4px;">
  310. 下载
  311. </el-button>
  312. </template>
  313. <template v-if="element.type === 'cascader'">
  314. <el-cascader
  315. :model-value="element.options.defaultValue"
  316. :options="element.options.remoteOptions"
  317. :placeholder="element.options.placeholder"
  318. :filterable="element.options.filterable"
  319. :clearable="element.options.clearable"
  320. :disabled="element.options.disabled"
  321. :style="{ width: element.options.width }"
  322. />
  323. </template>
  324. </el-form-item>
  325. <template v-if="selectWidget?.key === element.key">
  326. <div absolute z-10 left-0 top="-.5" bg-blue-500 text-white p=".5 l-0 t-0" cursor-move :class="{'bg-yellow-500':element.type === 'grid'}">
  327. <i class="eva:move-outline" text-lg />
  328. </div>
  329. <div absolute z-10 right-0 bottom="-0.5" bg-blue-500 flex gap-1 p="1 r-.5" text-white cursor-pointer :class="{'bg-yellow-500':element.type === 'grid'}">
  330. <i class="fa6-regular:clone" @click.stop="handleCopyClick()" v-if="false" />
  331. <i class="fa6-regular:trash-can" @click.stop="handleDeleteClick()" v-if="!element.allDisable" />
  332. </div>
  333. </template>
  334. </div>
  335. </template>