当前位置:   article > 正文

关于el-form+el-table+表头部分内容和表单都是动态生成(动态绑定v-model)_el-table-column prop动态绑定

el-table-column prop动态绑定

首先一个小demo,请大佬教的

  1. <template>
  2. <view>
  3. <el-button type="primary" @click='tableData.push(obj)'>新增行</el-button>
  4. <el-button type="primary" @click='gettableData'>获取完整信息</el-button>
  5. <el-table :data="tableData" style="width: 100%">
  6. <el-table-column prop="date" label="日期" width="180">
  7. <template slot-scope="scope">
  8. <el-input v-model="scope.row.date" @change='getChange(scope.row)' placeholder="请输入内容"></el-input>
  9. </template>
  10. </el-table-column>
  11. <el-table-column prop="name" label="姓名" width="180">
  12. <template slot-scope="scope">
  13. <el-input v-model="scope.row.name" placeholder="请输入内容"></el-input>
  14. </template>
  15. </el-table-column>
  16. <el-table-column prop="address" label="地址">
  17. <template slot-scope="scope">
  18. <el-input v-model="scope.row.address" placeholder="请输入内容"></el-input>
  19. </template>
  20. </el-table-column>
  21. <el-table-column :prop="item.name" :label="item.title" v-for="(item,idx) in titleList" :key="idx">
  22. <template slot-scope="scope">
  23. <el-input v-model="scope.row[item.name]" placeholder="请输入内容"></el-input>
  24. </template>
  25. </el-table-column>
  26. </el-table>
  27. </view>
  28. </template>
  29. <script>
  30. export default {
  31. data() {
  32. return {
  33. obj: {
  34. date: '',
  35. name: '',
  36. address: ''
  37. },
  38. tableData: [],
  39. titleList: []
  40. }
  41. },
  42. onLoad() {
  43. this.getList()
  44. },
  45. methods: {
  46. gettableData() {
  47. console.log('全部数据', this.tableData)
  48. },
  49. getChange(val) {
  50. console.log('当前行数据', val)
  51. },
  52. getList() {
  53. //假设这里获取前段行数据
  54. this.tableData = [{
  55. date: '2016-05-02',
  56. name: '王小虎',
  57. address: '上海市普陀区金沙江路 1518 弄'
  58. }, {
  59. date: '2016-05-04',
  60. name: '王小虎',
  61. address: '上海市普陀区金沙江路 1517 弄'
  62. }, {
  63. date: '2016-05-01',
  64. name: '王小虎',
  65. address: '上海市普陀区金沙江路 1519 弄'
  66. }, {
  67. date: '2016-05-03',
  68. name: '王小虎',
  69. address: '上海市普陀区金沙江路 1516 弄'
  70. }]
  71. //假设行数据获取完成后获取表头
  72. this.titleList = [{
  73. title: '动态表头1',
  74. name: 'ziduan1'
  75. }, {
  76. title: '动态表头2',
  77. name: 'ziduan2'
  78. }, {
  79. title: '动态表头3',
  80. name: 'ziduan3'
  81. }]
  82. //表头和行数据都获取完成之后进行预处理
  83. this.tableData.forEach(data=>{
  84. this.titleList.forEach(item=>{
  85. data[item.name]=''
  86. })
  87. })
  88. //拼接好的数据
  89. console.log(this.tableData)
  90. },
  91. }
  92. }
  93. </script>
  94. <style scoped lang="less">
  95. </style>

接下来是根据需求写的表单+表格,由于后端给的格式不适应表格数据格式,做了很多转换,最后提交的数据也做了格式转换。代码较糙,留着看看长个记性,毕竟折磨了好多天

页面效果

  1. <script lang='ts' setup>
  2. import PageHeader from '@/components/header/PageHeader.vue'
  3. import CustomButton from '@/components/button/CustomButton.vue'
  4. import MySearchInput from '@/components/search/MySearchInput.vue'
  5. import AdvancedSearch from '@/components/search/AdvancedSearch.vue'
  6. import { ref, reactive, toRaw, watch } from 'vue'
  7. import { ElTable, ElMessage } from 'element-plus'
  8. import { useRoute } from 'vue-router'
  9. import router from '@/router'
  10. import type { material } from '@/types/material'
  11. import { getConversionList, addAdjust } from '@/api/material'
  12. import { typrList } from '@/api/fieldType'
  13. import type { TableColumnCtx } from 'element-plus/es/components/table/src/table-column/defaults'
  14. import { notifyAPIResponse } from '@/utils/common'
  15. const dialogFormVisible = ref(false),
  16. arr: any = ref([]),
  17. arr1: any = ref([]),
  18. currentIndex = ref()
  19. const advanceSearchConfig = {
  20. formType: [
  21. {
  22. label: 'value',
  23. key: 'search',
  24. compType: 'ElInput',
  25. value: '',
  26. },
  27. ]
  28. }
  29. // do not use same name with ref
  30. const form = reactive({
  31. adjustState: '0',
  32. adjustTime: '',
  33. createBy: '',
  34. })
  35. const rules = reactive({
  36. createName: [
  37. {
  38. required: true,
  39. message: '请输入必填项'
  40. }
  41. ]
  42. })
  43. const cancel = () => {
  44. router.push({
  45. path: '/MaterialConversion/conversion'
  46. })
  47. }
  48. //获取物料类型列表,转换成数组渲染表头
  49. const getArrList = async () => {
  50. await typrList('').then(res => {
  51. arr.value = res.rows
  52. console.log(arr.value);
  53. for (let i of arr.value) {
  54. let obj1 = {
  55. name: i.typeName + '编码',
  56. typeId: i.typeId,
  57. }
  58. let obj2 = {
  59. name: i.typeName + '名称',
  60. typeId: i.typeId,
  61. }
  62. arr1.value.push(obj1)
  63. arr1.value.push(obj2)
  64. }
  65. })
  66. onload()
  67. console.log(arr1.value, 'arr1');
  68. }
  69. getArrList()
  70. const onload = () => {
  71. //@ts-ignore
  72. form1.tableData1.forEach(data => {
  73. //@ts-ignore
  74. arr1.value.forEach(item => {
  75. data[item.name] = ''
  76. })
  77. })
  78. }
  79. //获取物料信息表
  80. const getMerList = async () => {
  81. const { rows: list, total } = await getConversionList({
  82. ...toRaw(pageConfig),
  83. ...route.query,
  84. }).catch(() => { })
  85. tableData.value = list
  86. pageConfig.total = total
  87. }
  88. // 物料页码跳转
  89. const handleSizeChange = (val: number) => {
  90. console.log(`${val} items per page`)
  91. pageConfig.pageSize = val
  92. router.push({
  93. query: {
  94. ...route.query,
  95. ...pageConfig,
  96. },
  97. })
  98. }
  99. const handleCurrentChange = (val: number) => {
  100. console.log(`current page: ${val}`)
  101. pageConfig.pageNum = val
  102. router.push({
  103. query: {
  104. ...route.query,
  105. ...pageConfig,
  106. },
  107. })
  108. }
  109. const pageConfig = reactive({
  110. pageNum: 1,
  111. pageSize: 20,
  112. total: 0,
  113. })
  114. //明细页码跳转
  115. const pageConfig1 = reactive({
  116. pageNum: 1,
  117. pageSize: 10,
  118. total: 0,
  119. })
  120. const handleSizeChange1 = (val: number) => {
  121. console.log(`${val} items per page`)
  122. pageConfig.pageSize = val
  123. }
  124. const handleCurrentChange1 = (val: number) => {
  125. console.log(`current page: ${val}`)
  126. pageConfig.pageNum = val
  127. }
  128. const tableRef = ref<InstanceType<typeof ElTable>>(),
  129. tableData = ref<Array<material>>([]),
  130. route = useRoute(),
  131. loading = ref(true),
  132. form1: any = reactive({
  133. tableData1: []
  134. }),
  135. selectedNames: any = ref([])
  136. watch(
  137. () => route.query,
  138. () => {
  139. getMerList()
  140. }
  141. )
  142. const addLine = () => {
  143. let dataline = {
  144. state: '0',
  145. materialNumber: '',
  146. materialName: '',
  147. }
  148. let dataline1 = {
  149. state: '',
  150. materialNumber: '',
  151. materialName: '',
  152. }
  153. //@ts-ignore
  154. form1.tableData1.push(dataline)
  155. form1.tableData1.push(dataline1)
  156. console.log(form1.tableData1, 'qqq');
  157. }
  158. interface SpanMethodProps {
  159. row: material
  160. column: TableColumnCtx<material>
  161. rowIndex: number
  162. columnIndex: number
  163. }
  164. const objectSpanMethod = ({
  165. row,
  166. column,
  167. rowIndex,
  168. columnIndex,
  169. }: SpanMethodProps) => {
  170. if (columnIndex === 0 || columnIndex === 1 || columnIndex === 2 || columnIndex === 3 || columnIndex === 4) {
  171. if (rowIndex % 2 === 0) {
  172. return {
  173. rowspan: 2,
  174. colspan: 1,
  175. }
  176. } else {
  177. return {
  178. rowspan: 0,
  179. colspan: 0,
  180. }
  181. }
  182. }
  183. }
  184. const searchList = (current: any) => {
  185. // console.log(current, 'current');
  186. currentIndex.value = current
  187. dialogFormVisible.value = true
  188. getMerList()
  189. }
  190. const subSelected = () => {
  191. const rows = tableRef.value?.getSelectionRows()
  192. if (rows.length === 0 || rows.length > 1)
  193. return ElMessage.error('必须且只能选中一行')
  194. console.log(currentIndex.value);
  195. console.log(rows[0]);
  196. form1.tableData1[currentIndex.value].materialName = rows[0].materialName
  197. form1.tableData1[currentIndex.value].materialNumber = rows[0].materialNumber
  198. form1.tableData1[currentIndex.value].materialId = rows[0].materialId
  199. selectedNames.value = rows[0].names
  200. for (let i of selectedNames.value) {
  201. form1.tableData1[currentIndex.value][i.typeName + '编码'] = i.num
  202. form1.tableData1[currentIndex.value][i.typeName + '名称'] = i.name
  203. }
  204. console.log(form1.tableData1, '......');
  205. dialogFormVisible.value = false
  206. }
  207. const subdata = () => {
  208. let children: any = [],
  209. subobj = {}
  210. console.log(form1.tableData1, '88888888');
  211. for (let i = 0; i < form1.tableData1.length; i++) {
  212. if (i % 2 == 0) {
  213. let obj = {
  214. materialId: '',
  215. state: '',
  216. entries: []
  217. }
  218. obj.state = form1.tableData1[i].state
  219. obj.materialId = form1.tableData1[i].materialId
  220. children.push(obj)
  221. } else {
  222. for (let k = 0; k < arr1.value.length; k++) {
  223. if (arr1.value[k].name in form1.tableData1[i]) {
  224. if (k % 2 == 0) {
  225. let entriesObj = {
  226. typeId: '',
  227. name: '',
  228. num: ''
  229. }
  230. entriesObj.typeId = arr1.value[k].typeId
  231. entriesObj.name = form1.tableData1[i][arr.value[k / 2].typeName + '名称']
  232. entriesObj.num = form1.tableData1[i][arr.value[k / 2].typeName + '编码']
  233. // console.log(entriesObj, 'entriesObj');
  234. console.log(children[(i - 1) / 2], 'children[i / 2]');
  235. children[(i - 1) / 2].entries.push(entriesObj)
  236. }
  237. }
  238. }
  239. }
  240. }
  241. console.log(children, 'childrenchildrenchildren');
  242. subobj = {
  243. children,
  244. ...form
  245. }
  246. notifyAPIResponse(() => addAdjust(subobj)).then((isOk) => {
  247. if (!isOk) return
  248. router.go(-1)
  249. })
  250. }
  251. // 选中某一行修改或移除
  252. const getDelIndex = (i: any) => {
  253. form1.tableData1.splice(i, 2)
  254. }
  255. </script>
  256. <template>
  257. <div>
  258. <!-- MaterialConversion/addConversion -->
  259. <PageHeader>
  260. <template #left>
  261. <span class="title">物料转化方案调整单</span>
  262. </template>
  263. <template #right>
  264. <CustomButton type="plain">流程进度</CustomButton>
  265. <CustomButton type="plain">快速跳转</CustomButton>
  266. </template>
  267. </PageHeader>
  268. <a-card class="core">
  269. <div class="title1">基本信息</div>
  270. <div>
  271. <el-form :model="form" label-width="120px" ref="vForm" :rules="rules">
  272. <el-row :gutter="20">
  273. <el-col :span="6">
  274. <el-form-item label="单据时间">
  275. <el-date-picker v-model="form.adjustTime" type="date" disabled />
  276. </el-form-item>
  277. </el-col>
  278. <el-col :span="6">
  279. <el-form-item label="创建人" prop="createName">
  280. <el-input v-model="form.createBy" disabled />
  281. </el-form-item>
  282. </el-col>
  283. <el-col :span="6">
  284. <el-form-item label="状态">
  285. <el-select v-model="form.adjustState" placeholder="请输入">
  286. <el-option label="创建" value="0" />
  287. </el-select>
  288. </el-form-item>
  289. </el-col>
  290. </el-row>
  291. </el-form>
  292. </div>
  293. </a-card>
  294. <a-card class="core">
  295. <div class="title1">明细信息</div>
  296. <header class="flex justify-between mt-5">
  297. <div>
  298. <CustomButton type="plain" @click="addLine">新增行</CustomButton>
  299. <CustomButton type="plain">删除行</CustomButton>
  300. </div>
  301. </header>
  302. <!-- 明细信息表格 -->
  303. <el-form :model="form1">
  304. <el-table ref="tableRef" :data="form1.tableData1" style="width: 100%" v-bind="$attrs"
  305. :span-method="objectSpanMethod" :row-style="{ height: '40px' }">
  306. <el-table-column type="selection" width="55" />
  307. <el-table-column min-width="80" label="操作" align="center">
  308. <template #default="scope">
  309. <el-button text type="danger" @click="getDelIndex(scope.$index)">删除</el-button>
  310. </template>
  311. </el-table-column>
  312. <el-table-column min-width="150" label="状态">
  313. <template #default="scope">
  314. <el-select v-model="scope.row.state">
  315. <el-option label="正常" value="0" />
  316. </el-select>
  317. </template>
  318. </el-table-column>
  319. <el-table-column min-width="150" label="物料编码">
  320. <template #default="scope">
  321. <el-input v-model="scope.row.materialNumber" style="width:150px">
  322. <template #suffix>
  323. <Search style="width: 1em; height: 1em; margin-right: 8px" class="cursor-pointer"
  324. @click="searchList(scope.$index)" />
  325. </template>
  326. </el-input>
  327. </template>
  328. </el-table-column>
  329. <el-table-column min-width="150" label="物料名称">
  330. <template #default="scope">
  331. <el-input v-model="scope.row.materialName" style="width:150px"></el-input>
  332. </template>
  333. </el-table-column>
  334. <el-table-column min-width="150" v-for="item, i in arr1" :label="item.name" :prop="item.val" :key="i">
  335. <template #default="scope">
  336. <span v-show="scope.$index % 2 == 0">
  337. <el-input v-model="scope.row[item.name]" style="width:150px" disabled></el-input>
  338. <!-- {{ scope.row[item.name] || '' }} -->
  339. </span>
  340. <el-input v-model="scope.row[item.name]" style="width:150px" v-show="scope.$index % 2 !== 0">
  341. </el-input>
  342. </template>
  343. </el-table-column>
  344. </el-table>
  345. </el-form>
  346. <div class="mt-2">
  347. <el-pagination v-model:currentPage="pageConfig1.pageNum" v-model:page-size="pageConfig1.pageSize"
  348. :page-sizes="[10, 20, 30, 40]" layout="total, sizes, prev, pager, next, jumper"
  349. :total="pageConfig1.total" @size-change="handleSizeChange1" @current-change="handleCurrentChange1" />
  350. </div>
  351. </a-card>
  352. <el-dialog v-model="dialogFormVisible" title="选择物料" class="pb-6" width="40%">
  353. <div class="flex justify-end items-center">
  354. <MySearchInput class="ml-8" main-name="search"></MySearchInput>
  355. <AdvancedSearch class="ml-8" :formType="advanceSearchConfig.formType"></AdvancedSearch>
  356. </div>
  357. <el-table :data="tableData" max-height="500px" ref="tableRef">
  358. <el-table-column type="selection" />
  359. <el-table-column prop="materialName" label="物料名称" min-width="150" />
  360. <el-table-column prop="materialNumber" label="物料编码" min-width="150" />
  361. <el-table-column prop="materialFName" label="ERP物料名称" min-width="150" />
  362. <el-table-column prop="materialFNumber" label="ERP物料编码" min-width="150" />
  363. </el-table>
  364. <div class="mt-2">
  365. <el-pagination v-model:currentPage="pageConfig.pageNum" v-model:page-size="pageConfig.pageSize"
  366. :page-sizes="[20, 30, 40, 100]" layout="total, sizes, prev, pager, next, jumper"
  367. :total="pageConfig.total" @size-change="handleSizeChange" @current-change="handleCurrentChange" />
  368. </div>
  369. <div style="float:right" class="mt-2">
  370. <el-button @click="dialogFormVisible = false">关闭</el-button>
  371. <el-button type="primary" @click="subSelected">确定</el-button>
  372. </div>
  373. </el-dialog>
  374. <a-card class="footer flex justify-end">
  375. <CustomButton type="plain" @click="cancel">取消</CustomButton>
  376. <!-- <CustomButton type="plain">保存</CustomButton> -->
  377. <CustomButton type="primary" @click="subdata">提交</CustomButton>
  378. </a-card>
  379. </div>
  380. </template>
  381. <style lang = "scss" scoped>
  382. .title {
  383. font-size: 20px;
  384. margin-left: 10px;
  385. }
  386. .title1 {
  387. font-size: 16px;
  388. font-weight: 700;
  389. }
  390. .core {
  391. margin: 0 8px 8px 8px;
  392. }
  393. :deep(.el-date-editor.el-input, .el-date-editor.el-input__wrapper) {
  394. width: 100%
  395. }
  396. .footer {
  397. margin: 0 8px 8px 8px;
  398. }
  399. :deep(.ant-card-body) {
  400. padding: 10px;
  401. }
  402. .el-table .cell {
  403. display: flex;
  404. align-items: center;
  405. }
  406. .el-pagination {
  407. justify-content: end;
  408. }
  409. .el-pagination__total {
  410. margin-right: auto !important;
  411. }
  412. .el-table--fit {
  413. margin-top: 20px;
  414. border-top: 1px solid var(--el-border-color-lighter);
  415. }
  416. </style>
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小丑西瓜9/article/detail/426280
推荐阅读
相关标签
  

闽ICP备14008679号