|
@@ -0,0 +1,157 @@
|
|
|
|
+<template>
|
|
|
|
+ <div class="resume-box">
|
|
|
|
+ <div class="resume-header">
|
|
|
|
+ <div class="resume-title">{{ $t('resume.projectExperience') }}</div>
|
|
|
|
+ <v-btn variant="text" color="primary" prepend-icon="mdi-plus-box" @click="isEdit = true; type = 'add'">{{ $t('common.add') }}</v-btn>
|
|
|
|
+ </div>
|
|
|
|
+ <div v-if="isEdit" class="edit">
|
|
|
|
+ <h4 class="label-title my-3 mx-2"> {{ type === 'add' ? $t('common.add') : $t('common.edit') }}{{ $t('resume.projectExperience') }}</h4>
|
|
|
|
+ <CtForm ref="formPageRef" :items="items" style="width: 100%;"></CtForm>
|
|
|
|
+ <div class="text-end">
|
|
|
|
+ <v-btn class="half-button mr-3" variant="tonal" @click="isEdit = false; type = ''">{{ $t('common.cancel') }}</v-btn>
|
|
|
|
+ <v-btn color="primary" class="half-button" @click="handleSave">{{ $t('common.save') }}</v-btn>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ <div v-else v-for="(k, i) in projectExp" :key="i" class="exp mx-n2" @mouseenter="k.active = true" @mouseleave="k.active = false">
|
|
|
|
+ <span class="float-right" v-if="k.active">
|
|
|
|
+ <v-btn variant="text" color="primary" prepend-icon="mdi-square-edit-outline" @click="handleEdit(k)">{{ $t('common.edit') }}</v-btn>
|
|
|
|
+ <v-btn variant="text" color="primary" prepend-icon="mdi-trash-can-outline" @click="handleDelete(k)">{{ $t('common.delete') }}</v-btn>
|
|
|
|
+ </span>
|
|
|
|
+ <div v-for="(val, index) in desc" :key="index" class="my-1">
|
|
|
|
+ <span class="label-title">{{ val.label }}</span>
|
|
|
|
+ <span v-if="Array.isArray(val.value)">{{ timesTampChange(k[val.value[0]]).slice(0, 10) }} 至 {{ timesTampChange(k[val.value[1]]).slice(0, 10) }}</span>
|
|
|
|
+ <span>{{ k[val.value] }}</span>
|
|
|
|
+ </div>
|
|
|
|
+ <div v-if="i !== projectExp.length -1" class="border-bottom-dashed mt-3"></div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+</template>
|
|
|
|
+
|
|
|
|
+<script setup name="projectExperience">
|
|
|
|
+import { ref, shallowRef } from 'vue'
|
|
|
|
+import { getTimeStamp, timesTampChange } from '@/utils/date'
|
|
|
|
+import { saveResumeProjectExp, getResumeProjectExp, deleteResumeProjectExp } from '@/api/resume'
|
|
|
|
+import CtForm from '@/components/CtForm'
|
|
|
|
+import Snackbar from '@/plugins/snackbar'
|
|
|
|
+import Confirm from '@/plugins/confirm'
|
|
|
|
+
|
|
|
|
+const isEdit = ref(false)
|
|
|
|
+const formPageRef = ref()
|
|
|
|
+const type = ref('')
|
|
|
|
+const editId = ref(null)
|
|
|
|
+const items = ref({
|
|
|
|
+ options: [
|
|
|
|
+ {
|
|
|
|
+ type: 'text',
|
|
|
|
+ key: 'name',
|
|
|
|
+ value: '',
|
|
|
|
+ label: '项目名称 *',
|
|
|
|
+ rules: [v => !!v || '请输入项目名称']
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ type: 'datepicker',
|
|
|
|
+ key: 'startTime',
|
|
|
|
+ value: shallowRef(null),
|
|
|
|
+ col: 6,
|
|
|
|
+ label: '项目开始时间 *',
|
|
|
|
+ flexStyle: 'mr-3',
|
|
|
|
+ rules: [v => !!v || '请选择项目开始时间']
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ type: 'datepicker',
|
|
|
|
+ key: 'endTime',
|
|
|
|
+ value: shallowRef(null),
|
|
|
|
+ col: 6,
|
|
|
|
+ label: '项目结束时间 *',
|
|
|
|
+ rules: [v => !!v || '请选择项目结束时间']
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ type: 'textarea',
|
|
|
|
+ key: 'content',
|
|
|
|
+ value: '',
|
|
|
|
+ label: '项目描述 *',
|
|
|
|
+ counter: '500',
|
|
|
|
+ rules: [
|
|
|
|
+ value => {
|
|
|
|
+ if (value) return true
|
|
|
|
+ return '请输入项目描述'
|
|
|
|
+ },
|
|
|
|
+ value => {
|
|
|
|
+ if (value?.length <= 500) return true
|
|
|
|
+ return '请输入2-200个字符'
|
|
|
|
+ }
|
|
|
|
+ ]
|
|
|
|
+ }
|
|
|
|
+ ]
|
|
|
|
+})
|
|
|
|
+
|
|
|
|
+// 获取项目经历
|
|
|
|
+const projectExp = ref([])
|
|
|
|
+const getResumeTrainExpData = async () => {
|
|
|
|
+ const data = await getResumeProjectExp()
|
|
|
|
+ projectExp.value = data
|
|
|
|
+}
|
|
|
|
+getResumeTrainExpData()
|
|
|
|
+
|
|
|
|
+// 保存项目经历
|
|
|
|
+const handleSave = async () => {
|
|
|
|
+ const { valid } = await formPageRef.value.formRef.validate()
|
|
|
|
+ if (!valid) return
|
|
|
|
+ const obj = {}
|
|
|
|
+ items.value.options.forEach(e => {
|
|
|
|
+ if (e.key === 'startTime' || e.key == 'endTime') obj[e.key] = shallowRef(getTimeStamp(e.value))
|
|
|
|
+ else obj[e.key] = e.value
|
|
|
|
+ })
|
|
|
|
+ if (editId.value) obj.id = editId.value
|
|
|
|
+ await saveResumeProjectExp(obj)
|
|
|
|
+ Snackbar.success('保存成功!')
|
|
|
|
+ isEdit.value = false
|
|
|
|
+ type.value = ''
|
|
|
|
+ editId.value = null
|
|
|
|
+ getResumeTrainExpData()
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+const handleEdit = (item) => {
|
|
|
|
+ editId.value = item.id
|
|
|
|
+ items.value.options.forEach(e => {
|
|
|
|
+ if (e.key === 'startTime' || e.key == 'endTime') e.value = timesTampChange(item[e.key]).slice(0, 10)
|
|
|
|
+ else e.value = item[e.key]
|
|
|
|
+ })
|
|
|
|
+ isEdit.value = true
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// 删除项目经历
|
|
|
|
+const handleDelete = ({ id }) => {
|
|
|
|
+ Confirm('系统提示', '是否确认删除此项目经历?').then(async () => {
|
|
|
|
+ await deleteResumeProjectExp(id)
|
|
|
|
+ Snackbar.success('删除成功!')
|
|
|
|
+ getResumeTrainExpData()
|
|
|
|
+ })
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+const desc = [
|
|
|
|
+ { label: '项目名称:', value: 'name' },
|
|
|
|
+ { label: '项目时间:', value: ['startTime', 'endTime'] },
|
|
|
|
+ { label: '项目描述:', value: 'content' }
|
|
|
|
+]
|
|
|
|
+</script>
|
|
|
|
+
|
|
|
|
+<style scoped lang="scss">
|
|
|
|
+.exp {
|
|
|
|
+ font-size: 15px;
|
|
|
|
+ cursor: pointer;
|
|
|
|
+ border-radius: 6px;
|
|
|
|
+ padding: 2px 10px 8px;
|
|
|
|
+ &:hover {
|
|
|
|
+ background-color: #f8f8f8;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+.label-title {
|
|
|
|
+ color: #666;
|
|
|
|
+}
|
|
|
|
+.edit {
|
|
|
|
+ background-color: #f8f8f8;
|
|
|
|
+ padding: 2px 10px 8px;
|
|
|
|
+ border-radius: 6px;
|
|
|
|
+}
|
|
|
|
+</style>
|