WorkTable.vue 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. <template>
  2. <div class="casually-name">
  3. <div class="star-title">
  4. <i></i>
  5. <span>工作经历(按照时间倒序填写)</span>
  6. </div>
  7. <el-tag class="add-tag" type="primary" effect="plain" v-if="!readOnly" @click="onAddItem()"
  8. >+ 新增</el-tag
  9. >
  10. <div class="my-portrait-card">
  11. <el-form style="width: 100%" v-if="tableData.length > 0">
  12. <div v-for="(item, index) in tableData" class="card-item" :key="index">
  13. <el-row :gutter="66">
  14. <el-col :span="12">
  15. <el-form-item label="起始时间">
  16. <el-date-picker
  17. v-model="item['startTime']"
  18. style="width: 100%"
  19. placeholder=""
  20. type="date"
  21. value-format="x"
  22. :disabled="!item.isEdit"
  23. />
  24. </el-form-item>
  25. </el-col>
  26. <el-col :span="12">
  27. <el-form-item label="终止时间">
  28. <el-date-picker
  29. v-model="item['endTime']"
  30. style="width: 100%"
  31. placeholder=""
  32. type="date"
  33. value-format="x"
  34. :disabled="!item.isEdit"
  35. />
  36. </el-form-item>
  37. </el-col>
  38. </el-row>
  39. <el-row :gutter="66">
  40. <el-col :span="12">
  41. <el-form-item label="工作单位">
  42. <el-input
  43. placeholder="请输入单位名称"
  44. v-model="item.workLocation"
  45. :disabled="!item.isEdit"
  46. />
  47. </el-form-item>
  48. </el-col>
  49. <el-col :span="12">
  50. <el-form-item label="岗位">
  51. <el-input v-model="item.post" :disabled="!item.isEdit" />
  52. </el-form-item>
  53. </el-col>
  54. </el-row>
  55. <el-row :gutter="66">
  56. <el-col :span="12">
  57. <el-form-item label="离职原因">
  58. <el-input v-model="item.resignReason" :disabled="!item.isEdit" />
  59. </el-form-item>
  60. </el-col>
  61. <el-col :span="12">
  62. <el-form-item label="是否有竞业限制/未尽法律事宜">
  63. <el-select v-model="item.jyxy" style="width: 100%" :disabled="!item.isEdit">
  64. <el-option value="1" label="是" />
  65. <el-option value="0" label="否" />
  66. </el-select>
  67. </el-form-item>
  68. </el-col>
  69. </el-row>
  70. <el-row :gutter="66">
  71. <el-col :span="24" v-if="item.jyxy === '1'">
  72. <el-form-item label="具体条款">
  73. <el-input
  74. type="textarea"
  75. v-model="item.competitionDetail"
  76. :disabled="!item.isEdit"
  77. />
  78. </el-form-item>
  79. </el-col>
  80. </el-row>
  81. <div class="btn_group" v-if="!onlyRead">
  82. <el-button type="primary" size="small" @click="onSaveItem(item)" v-if="item.isEdit">
  83. 保存
  84. </el-button>
  85. <el-button type="primary" size="small" @click="onEditItem(index)" v-else>
  86. 编辑
  87. </el-button>
  88. <el-button type="primary" size="small" @click="deleteRow(index)"> 删除 </el-button>
  89. </div>
  90. </div>
  91. </el-form>
  92. <p v-else style="text-align: center; width: 100%; color: #909399; font-size: 13px"
  93. >暂无数据</p
  94. >
  95. </div>
  96. </div>
  97. </template>
  98. <script lang="ts" setup>
  99. /**
  100. * @description 工作经历
  101. */
  102. import { FormValidate } from '@/utils/formValidate'
  103. import { cloneDeep } from 'lodash-es'
  104. interface ITable {
  105. id?: string
  106. userId?: string
  107. workLocation?: string // 工作单位
  108. post?: string // 职位
  109. startTime?: string // 开始时间
  110. endTime?: string // 结束时间
  111. resignReason?: string // 离职原因
  112. jyxy?: string // 是否有竞业限制/未尽法律事宜
  113. competitionDetail?: string // 具体条款
  114. isEdit?: boolean // 是否可编辑
  115. }
  116. const tableData = ref<ITable[]>([])
  117. const $emit = defineEmits<{
  118. (e: 'onSave', v: any): void
  119. }>()
  120. interface IProps {
  121. defaultData: any[]
  122. onlyRead?: boolean
  123. }
  124. const props = defineProps<IProps>()
  125. const { defaultData } = props
  126. const readOnly = ref(props.onlyRead)
  127. watch(
  128. () => props.onlyRead,
  129. (newVal) => {
  130. readOnly.value = newVal
  131. }
  132. )
  133. watch(
  134. () => props.defaultData,
  135. (newVal) => {
  136. tableData.value = newVal.map((item: any) => {
  137. return {
  138. ...item,
  139. isEdit: typeof item['isEdit'] === 'boolean' ? item['isEdit'] : false
  140. }
  141. })
  142. }
  143. )
  144. onMounted(() => {
  145. if (defaultData && defaultData.length) {
  146. tableData.value = defaultData.map((item: any) => {
  147. return {
  148. ...item,
  149. isEdit: false
  150. }
  151. })
  152. }
  153. })
  154. // 新增行
  155. const onAddItem = () => {
  156. tableData.value.push({
  157. workLocation: '',
  158. post: '',
  159. startTime: '',
  160. endTime: '',
  161. resignReason: '',
  162. jyxy: '1',
  163. competitionDetail: '',
  164. isEdit: true
  165. })
  166. }
  167. const ruleFields = [
  168. {
  169. name: 'startTime',
  170. message: '起始时间不能为空!'
  171. },
  172. {
  173. name: 'endTime',
  174. message: '终止时间不能为空!'
  175. },
  176. {
  177. name: 'workLocation',
  178. message: '工作单位!'
  179. },
  180. {
  181. name: 'post',
  182. message: '岗位!'
  183. },
  184. {
  185. name: 'resignReason',
  186. message: '离职原因不能为空!'
  187. }
  188. ]
  189. // 保存行
  190. const onSaveItem = (item: ITable) => {
  191. // console.log(item)
  192. // FormValidate.validate(
  193. // item,
  194. // ruleFields
  195. // )((state, obj) => {
  196. // console.log(state)
  197. // console.log(obj)
  198. // })
  199. item.isEdit = false
  200. const changeData = cloneDeep(tableData.value).map((item: any) => {
  201. return item
  202. })
  203. $emit('onSave', changeData)
  204. }
  205. // 编辑行
  206. const onEditItem = (index: number) => {
  207. tableData.value[index].isEdit = true
  208. }
  209. // 删除
  210. const deleteRow = (index: number) => {
  211. tableData.value.splice(index, 1)
  212. const changeData = cloneDeep(tableData.value).map((item: any) => {
  213. delete item.isEdit
  214. return item
  215. })
  216. $emit('onSave', changeData)
  217. }
  218. </script>
  219. <style scoped lang="scss">
  220. .casually-name {
  221. position: relative;
  222. }
  223. .star-title {
  224. display: flex;
  225. align-items: center;
  226. margin-bottom: 8px;
  227. i {
  228. display: block;
  229. width: 16px;
  230. height: 16px;
  231. margin-right: 9px;
  232. background: url('../../../../assets/imgs/OA/mine/star.png') center no-repeat;
  233. background-size: 100%;
  234. }
  235. span {
  236. font-size: 18px;
  237. font-weight: bold;
  238. color: #000000;
  239. }
  240. }
  241. .add-tag {
  242. position: absolute;
  243. top: 2px;
  244. right: 0;
  245. cursor: pointer;
  246. }
  247. .detail-table {
  248. width: 100%;
  249. min-height: 100px;
  250. }
  251. .my-portrait-card {
  252. display: flex;
  253. padding: 20px 40px;
  254. background: linear-gradient(90deg, #f2f7ff 0%, rgb(245 249 255 / 0%) 100%);
  255. border: 1px solid #e4e9f1;
  256. border-radius: 4px;
  257. flex-wrap: wrap;
  258. .btn_group {
  259. text-align: right;
  260. }
  261. .card-item {
  262. padding: 30px 0px;
  263. border-bottom: 1px solid #e4e9f1;
  264. &:first-child {
  265. padding-top: 0px;
  266. }
  267. &:last-child {
  268. border-bottom: 0px;
  269. padding-bottom: 0px;
  270. }
  271. }
  272. }
  273. </style>