index.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381
  1. <template>
  2. <el-container>
  3. <el-header height="82">
  4. <el-form ref="form" :form="form" :size="size" label-suffix=":" @submit.native.prevent>
  5. <el-row :gutter="10">
  6. <el-col v-for="item in formConfigs.formConfigA" :key="item.name" :span="item.span || 18">
  7. <el-form-item :rules="item.rules" :label="item.label" :prop="item.name" :label-width="item.label ? '100px' : ''">
  8. <el-input
  9. v-if="item.type === 'input' || item.type === ''"
  10. v-model="form[item.name]"
  11. :style="item.style"
  12. :disabled="item.disabled"
  13. clearable
  14. :prefix-icon="item.prefixIcon"
  15. :suffix-icon="item.suffixIcon"
  16. :show-word-limit="item.showWordLimit"
  17. :type="item.inputType"
  18. :rows="item.rows"
  19. :autosize="item.autosize"
  20. :placeholder="`${$t('common.pleaseInput')} ${item.placeholder}`"
  21. @keyup.enter.native="onSubmit"
  22. />
  23. <qselect
  24. v-else-if="item.type === 'select'"
  25. :placeholder="`${$t('common.pleaseChoice')} ${item.placeholder}`"
  26. :code="item.code"
  27. :remote-api="item.remoteApi"
  28. :filters="item.filters"
  29. :value.sync="form[item.name]"
  30. :option-field="item.remoteApi?{ keyField: 'id', labelField: 'name', valueField: 'id' }:{ keyField: 'value', labelField: 'text', valueField: 'value' }"
  31. :remote="!!item.remote"
  32. :search-filed="item.searchFiled"
  33. :remote-data-query="item.remoteDataQuery"
  34. />
  35. <qcascader
  36. v-else-if="item.type === 'cascader'"
  37. :api="item.api"
  38. :data-query="item.dataquery"
  39. :multiple="item.multiple"
  40. :check-strictly="item.checkStrictly"
  41. :value.sync="form[item.name]"
  42. />
  43. <el-date-picker
  44. v-else-if="item.type === 'date'"
  45. v-model="form[item.name]"
  46. :type="item.dateType"
  47. :style="item.style"
  48. :align="item.align"
  49. range-separator="至"
  50. :start-placeholder="item.startPlaceholder"
  51. :end-placeholder="item.endPlaceholder"
  52. :disabled="item.disabled"
  53. :unlink-panels="item.unlinkPanels || true"
  54. :value-format="item.valueFormat"
  55. :default-value="item.defaultValue"
  56. :default-time="item.defaultTime"
  57. :placeholder="`${$t('common.pleaseChoice')} ${item.placeholder}`"
  58. :picker-options="item.pickerOptions"
  59. />
  60. <el-time-select
  61. v-else-if="item.type === 'time'"
  62. v-model="form[item.name]"
  63. :style="item.style"
  64. :disabled="item.disabled"
  65. :picker-options="item.pickerOptions?item.pickerOptions:{ start: '08:00', step: '00:05', end: '22:00' }"
  66. :placeholder="`${$t('common.pleaseChoice')} ${item.placeholder}`"
  67. />
  68. <div v-else-if="item.type === 'minmax'" class="minmax-box">
  69. <el-input-number
  70. v-model="form[item.name][0]"
  71. :step="item.step || 1"
  72. :min="item.min || 0"
  73. :controls="false"
  74. class="minmax-input"
  75. :precision="item.precision"
  76. :disabled="item.disabled"
  77. :placeholder="`${$t('common.pleaseInput')} ${item.minPlaceholder}`"
  78. />
  79. <div class="division-line">-</div>
  80. <el-input-number
  81. v-model="form[item.name][1]"
  82. :step="item.step || 1"
  83. :min="item.min || 0"
  84. class="minmax-input"
  85. :controls="false"
  86. :precision="item.precision"
  87. :disabled="item.disabled"
  88. :placeholder="`${$t('common.pleaseInput')} ${item.maxPlaceholder}`"
  89. />
  90. </div>
  91. </el-form-item>
  92. </el-col>
  93. <el-col :offset="selfAdaption" :span="6" style="text-align: right;">
  94. <el-button v-if="folding" :size="size" @click="show = !show">
  95. {{ show ? "折叠" : "展开" }}
  96. </el-button>
  97. <el-button type="primary" :size="size" icon="el-icon-search" @click.prevent="onSubmit">{{ $t('common.search') }}</el-button>
  98. <el-button :size="size" icon="el-icon-brush" @click="resetForm()">{{ $t('common.reset') }}</el-button>
  99. </el-col>
  100. </el-row>
  101. <transition name="el-zoom-in-top">
  102. <el-row v-show="show" :gutter="10">
  103. <el-col v-for="item in formConfigs.formConfigB" :key="item.name" :span="item.span || 24">
  104. <el-form-item :rules="item.rules" :label="item.label" :prop="item.name" :label-width="item.label ? '100px' : ''">
  105. <el-input
  106. v-if="(item.type || input) === 'input'"
  107. v-model="form[item.name]"
  108. :style="item.style"
  109. :disabled="item.disabled"
  110. :prefix-icon="item.prefixIcon"
  111. :suffix-icon="item.suffixIcon"
  112. :show-word-limit="item.showWordLimit"
  113. :type="item.inputType"
  114. :rows="item.rows"
  115. :autosize="item.autosize"
  116. :placeholder="`${$t('common.pleaseInput')} ${item.placeholder}`"
  117. clearable
  118. @keyup.enter.native="onSubmit"
  119. />
  120. <option-set
  121. v-else-if="item.type === 'select'"
  122. :placeholder="`${$t('common.pleaseChoice')} ${item.placeholder}`"
  123. :code="item.code"
  124. :remote-api="item.remoteApi"
  125. :filters="item.filters"
  126. :value.sync="form[item.name]"
  127. :option-field="item.remoteApi?{ keyField: 'id', labelField: 'name', valueField: 'id' }:{ keyField: 'value', labelField: 'text', valueField: 'value' }"
  128. :remote="!!item.remote"
  129. :search-filed="item.searchFiled"
  130. :remote-data-query="item.remoteDataQuery"
  131. />
  132. <cascader
  133. v-else-if="item.type === 'cascader'"
  134. :api="item.api"
  135. :data-query="item.dataquery"
  136. :multiple="item.multiple"
  137. :check-strictly="item.checkStrictly"
  138. :value.sync="form[item.name]"
  139. />
  140. <el-date-picker
  141. v-else-if="item.type === 'date'"
  142. v-model="form[item.name]"
  143. :type="item.dateType"
  144. :style="item.style"
  145. range-separator="至"
  146. :start-placeholder="item.startPlaceholder"
  147. :end-placeholder="item.endPlaceholder"
  148. :disabled="item.disabled"
  149. :unlink-panels="item.unlinkPanels || true"
  150. :value-format="item.valueFormat"
  151. :default-value="item.defaultValue"
  152. :default-time="item.defaultTime"
  153. :placeholder="`${$t('common.pleaseChoice')} ${item.placeholder}`"
  154. />
  155. <el-time-select
  156. v-else-if="item.type === 'time'"
  157. v-model="form[item.name]"
  158. :style="item.style"
  159. :disabled="item.disabled"
  160. :picker-options="item.pickerOptions?item.pickerOptions:{ start: '08:00', step: '00:05', end: '22:00' }"
  161. :placeholder="`${$t('common.pleaseChoice')} ${item.placeholder}`"
  162. />
  163. <div v-else-if="item.type === 'minmax'" class="minmax-box">
  164. <el-input-number
  165. v-model="form[item.name][0]"
  166. :step="item.step || 1"
  167. :min="item.min || ''"
  168. :controls="false"
  169. class="minmax-input"
  170. :precision="item.precision"
  171. :disabled="item.disabled"
  172. :placeholder="`${$t('common.pleaseInput')} ${item.minPlaceholder}`"
  173. />
  174. <div class="division-line">-</div>
  175. <el-input-number
  176. v-model="form[item.name][1]"
  177. :step="item.step || 1"
  178. :min="item.min || ''"
  179. class="minmax-input"
  180. :controls="false"
  181. :precision="item.precision"
  182. :disabled="item.disabled"
  183. :placeholder="`${$t('common.pleaseInput')} ${item.maxPlaceholder}`"
  184. />
  185. </div>
  186. </el-form-item>
  187. </el-col>
  188. </el-row>
  189. </transition>
  190. </el-form>
  191. </el-header>
  192. <el-header height="120">
  193. <el-row :gutter="1" type="flex" justify="space-between">
  194. <el-col :offset="12" :span="20" style="text-align: right;">
  195. <el-button type="primary" :size="size" icon="el-icon-plus" @click="onCreate">添加</el-button>
  196. <el-button type="danger" :size="size" icon="el-icon-delete" @click="onDeleteBatch">批量删除</el-button>
  197. <el-button type="primary" :size="size" icon="el-icon-download" @click="onExport">{{ $t('common.export') }}</el-button>
  198. </el-col>
  199. </el-row>
  200. </el-header>
  201. </el-container>
  202. </template>
  203. <script>
  204. import { mapGetters } from 'vuex'
  205. import OptionSet from '@/components/OptionSet/index'
  206. import Cascader from '@/components/Cascader/index'
  207. export default {
  208. name: 'Query',
  209. components: {
  210. OptionSet,
  211. Cascader
  212. },
  213. props: {
  214. formConfig: {
  215. type: [Array, Object],
  216. default: () => {
  217. return {
  218. export: {
  219. size: 1000
  220. },
  221. items: []
  222. }
  223. }
  224. }
  225. // folding: {
  226. // type: Boolean,
  227. // default: () => true
  228. // }
  229. // form: {
  230. // type: Object,
  231. // default: () => {
  232. // return {}
  233. // }
  234. // }
  235. },
  236. data() {
  237. return {
  238. isExporting: false,
  239. show: false,
  240. form: {},
  241. folding: false
  242. }
  243. },
  244. computed: {
  245. ...mapGetters(['size', 'minMainHeight']),
  246. selfAdaption() {
  247. var totalSpan = 0
  248. this.formConfigs.formConfigA.forEach(item => {
  249. totalSpan += item.span === undefined ? 18 : item.span
  250. })
  251. return totalSpan > 18 ? 0 : 18 - totalSpan
  252. },
  253. formConfigs() {
  254. const returnVal = {
  255. formConfigA: [],
  256. formConfigB: []
  257. }
  258. let count = 6
  259. for (const v of this.formConfig.items) {
  260. count += v.span
  261. if (count <= 24) {
  262. returnVal.formConfigA.push(v)
  263. } else {
  264. returnVal.formConfigB.push(v)
  265. }
  266. }
  267. returnVal.export = this.formConfig.export
  268. // eslint-disable-next-line vue/no-side-effects-in-computed-properties
  269. this.folding = !(count <= 24)
  270. return returnVal
  271. }
  272. },
  273. created() {
  274. this.resetForm('created')
  275. },
  276. methods: {
  277. isEmpty(val) {
  278. if (!val && val !== 0 && val !== '') {
  279. return ''
  280. }
  281. if (Array.prototype.isPrototypeOf(val) && val.length === 0) {
  282. return []
  283. }
  284. if (Object.prototype.isPrototypeOf(val) && Object.keys(val).length === 0) {
  285. return {}
  286. }
  287. return val
  288. },
  289. onSubmit() {
  290. for (var k in this.form) {
  291. this.form[k] = this.isEmpty(this.form[k])
  292. }
  293. // eslint-disable-next-line no-redeclare
  294. for (var k in this.form) {
  295. if (Array.isArray(this.form[k])) {
  296. for (var i = this.form[k].length - 1; i >= 0; i--) {
  297. if (this.form[k][i] === undefined) {
  298. this.form[k].splice(i, 1)
  299. }
  300. }
  301. }
  302. }
  303. this.$emit('onSubmit', this.form)
  304. },
  305. onCreate() {
  306. this.$emit('onCreate')
  307. },
  308. onDeleteBatch() {
  309. this.$emit('onDeleteBatch')
  310. },
  311. deepCopy(data) {
  312. if (typeof data !== 'object') {
  313. return data
  314. }
  315. if (Array.isArray(data)) {
  316. return data.map(this.deepCopy)
  317. }
  318. const copyData = {}
  319. for (const [key, value] of Object.entries(data)) {
  320. copyData[key] = this.deepCopy(value)
  321. }
  322. return copyData
  323. },
  324. onExport() {
  325. for (var k in this.form) {
  326. this.form[k] = this.isEmpty(this.form[k])
  327. }
  328. // eslint-disable-next-line no-redeclare
  329. for (var k in this.form) {
  330. if (Array.isArray(this.form[k])) {
  331. for (var i = this.form[k].length - 1; i >= 0; i--) {
  332. if (this.form[k][i] === undefined) {
  333. this.form[k].splice(i, 1)
  334. }
  335. }
  336. }
  337. }
  338. const form = this.deepCopy(this.form)
  339. form.page = 1
  340. form.rows = this.formConfig.export.rows
  341. form.__export__ = true
  342. form.__name__ = this.formConfig.export.name
  343. this.$emit('onSubmit', form)
  344. },
  345. resetForm(val) {
  346. this.formCopy = {}
  347. for (const v of this.formConfig.items) {
  348. this.formCopy[v.name] = v.value === null ? '' : v.value || ''
  349. }
  350. this.form = JSON.parse(JSON.stringify(this.formCopy))
  351. if (val === 'created') return
  352. this.$emit('onSubmit', this.form)
  353. },
  354. handleClick(row) {
  355. console.log(row)
  356. }
  357. }
  358. }
  359. </script>
  360. <style scoped lang="scss">
  361. .minmax-box {
  362. display: flex;
  363. .minmax-input {
  364. width: calc((100% - 6px) / 2);
  365. }
  366. .division-line {
  367. padding: 0 2px;
  368. width: 6px;
  369. display: flex;
  370. justify-content: center;
  371. }
  372. }
  373. .el-date-editor.el-input,
  374. .el-range-editor.el-input__inner,
  375. .el-select {
  376. width: 100%;
  377. }
  378. </style>