2 Commits 23de2749f7 ... 7daa14deba

Tác giả SHA1 Thông báo Ngày
  lifanagju_citu 7daa14deba Merge branch 'dev' of https://git.citupro.com/zhengnaiwen_citu/menduner-admin into dev 3 ngày trước cách đây
  lifanagju_citu 25166c6a42 人才地图维护加tab 3 ngày trước cách đây

+ 343 - 0
src/views/menduner/system/talentMap/components/ImageImportEdit.vue

@@ -0,0 +1,343 @@
+<template>
+  <m-dialog title="名片解析" v-model:visible="show" :showDrawer="id !== null" :footer="false" @close="handleClose">
+    <div class="fullBox box-1" :class="{ 'box-2': id }">
+      <v-card class="upload-card d-flex flex-column align-center justify-center overflow-hidden" elevation="5">
+        <template v-if="file">
+          <div class="fullBox overflow-auto text-center">
+            <div class="change d-flex align-center justify-end pr-3 pt-3" v-if="!id">
+              <UploadBtn
+                :loading="loading"
+                :disabled="loading"
+                color="primary"
+                class="white--text"
+                @change="handleImport"
+              >
+                <v-icon left dark>mdi-cloud-upload</v-icon>
+                更换名片
+              </UploadBtn>
+              <v-btn color="primary" rounded class="buttons white--text ml-2" @click="handleAnalysis">
+                <v-icon left dark>mdi-file-arrow-left-right</v-icon>
+                解析
+              </v-btn>
+            </div>
+            <img width="100%" :src="previewUrl" style="max-width: 700px;" />
+          </div>
+        </template>
+        <template v-else>
+          <div>
+            <UploadBtn
+              :loading="loading"
+              :disabled="loading"
+              color="primary"
+              class="ma-2 white--text"
+              @change="handleImport"
+            >
+              <v-icon left dark>
+                mdi-cloud-upload
+              </v-icon>
+              点击上传
+            </UploadBtn>
+          </div>
+          <div>
+            <v-chip>请选择文件解析</v-chip>
+          </div>
+        </template>
+      </v-card>
+      <MCard v-if="id" class="show-card d-flex flex-column" title="名片解析" v-loading="loading">
+        <template #title>
+          <v-btn color="primary" class="buttons" rounded @click="handleUpdate">
+            <v-icon left>mdi-update</v-icon>
+            更新
+          </v-btn>
+        </template>
+        <div class="fullBox overflow-auto">
+          <MForm class="mt-3" :items="formItems" v-model="formQuery">
+            <template #baseInfo>
+              <div>
+                <v-subheader>基础信息</v-subheader>
+                <!-- <v-menu
+                  attach
+                  :nudge-width="200"
+                  offset-x
+                >
+                  <template v-slot:activator="{ on, attrs }">
+                    <v-avatar
+                      class="ma-3"
+                      v-bind="attrs"
+                      v-on="on">
+                      <img
+                        src="https://cdn.vuetifyjs.com/images/john.jpg"
+                        alt="John"
+                      >
+                    </v-avatar>
+                  </template>
+
+                  <v-card>
+                    <img
+                      style="display: block;"
+                      src="https://cdn.vuetifyjs.com/images/john.jpg"
+                      width="300"
+                      alt="John"
+                    >
+                  </v-card>
+                </v-menu> -->
+              </div>
+            </template>
+            <template #companyInfo>
+              <v-subheader>公司/酒店信息</v-subheader>
+            </template>
+            <template #relationship>
+              <v-subheader>联系方式</v-subheader>
+            </template>
+            <template #addressInfo>
+              <v-subheader>地址信息</v-subheader>
+            </template>
+            <template #career_path="{ item }">
+              <div class="flex-grow-1 flex-shrink-1">
+                <v-subheader>职业轨迹</v-subheader>
+                <div>
+                  <v-row v-for="(path, index) in formQuery[item.key]" :key="index">
+                    <v-col :cols="4"><v-text-field hide-details v-model="path.company_name" outlined dense label="酒店名称"/></v-col>
+                    <v-col :cols="1" class="d-flex align-center justify-center">
+                      <v-icon>mdi-minus</v-icon>
+                    </v-col>
+                    <v-col :cols="4"><v-text-field hide-details v-model="path.position" outlined dense label="职位名称"/></v-col>
+                    <v-col :cols="3">
+                      <v-btn color="primary" @click="addCareerPath(index)">添加</v-btn>
+                      <v-btn v-if="formQuery[item.key]?.length > 1" class="ml-2" color="error" @click="removeCareerPath(index)">删除</v-btn>
+                    </v-col>
+                  </v-row>
+                </div>
+              </div>
+            </template>
+            <template #systemInfo>
+              <div class="pb-3">
+                <v-subheader>系统信息</v-subheader>
+                  <div class="px-3 infoBox">
+                    <div class="mb-3">
+                      <span class="label">状态</span>
+                      <v-chip small :color="itemData.status === 'active' ? 'success' : 'error'">
+                        {{ itemData.status === 'active' ? '已启用' : '已禁用' }}
+                      </v-chip>
+                    </div>
+                    <div class="mb-3">
+                      <span class="label">创建时间</span>
+                      <v-chip small color="default">{{ itemData.created_at }}</v-chip>
+                    </div>
+                    <div class="mb-3">
+                      <span class="label">更新时间</span>
+                      <v-chip small color="default">{{ itemData.updated_at }}</v-chip>
+                    </div>
+                  </div>
+              </div>
+            </template>
+          </MForm>
+        </div>
+      </MCard>
+    </div>
+    <Linear text="解析中..." v-model:visible="linearLoading"/>
+  </m-dialog>
+</template>
+
+<script>
+import Linear from '@/components/Progress/linear.vue'
+import UploadBtn from '@/components/UploadBtn'
+import MDialog from '@/components/Dialog'
+import MCard from '@/components/MCard'
+import MForm from '@/components/MForm'
+// import { toBase64 } from '@/utils/file'
+import {
+  businessCardParse,
+  getBusinessCardImage,
+  updateBusinessCard
+} from '@/api/dataOrigin'
+export default {
+  name: 'ImageImportEdit',
+  components: {
+    MDialog,
+    MCard,
+    UploadBtn,
+    Linear,
+    MForm
+  },
+  data () {
+    return {
+      linearLoading: false,
+      loading: false,
+      show: false,
+      file: null,
+      previewUrl: null,
+      formItems: [
+        { slotName: 'baseInfo' },
+        { label: '中文姓名', key: 'name_zh', type: 'text', outlined: true, dense: true, col: 6 },
+        { label: '英文姓名', key: 'name_en', type: 'text', outlined: true, dense: true, col: 6 },
+        { label: '中文职位/头衔', key: 'title_zh', type: 'text', outlined: true, dense: true, col: 6 },
+        { label: '英文职位/头衔', key: 'title_en', type: 'text', outlined: true, dense: true, col: 6 },
+        { slotName: 'relationship' },
+        { label: '手机号码', key: 'mobile', type: 'text', outlined: true, dense: true, col: 4 },
+        { label: '固定电话', key: 'phone', type: 'text', outlined: true, dense: true, col: 4 },
+        { label: '电子邮箱', key: 'email', type: 'text', outlined: true, dense: true, col: 4 },
+        { slotName: 'companyInfo' },
+        { label: '中文酒店/公司名称', key: 'hotel_zh', type: 'text', outlined: true, dense: true, col: 6 },
+        { label: '英文酒店/公司名称', key: 'hotel_en', type: 'text', outlined: true, dense: true, col: 6 },
+        { label: '中文品牌名称', key: 'brand_zh', type: 'text', outlined: true, dense: true, col: 6 },
+        { label: '英文品牌名称', key: 'brand_en', type: 'text', outlined: true, dense: true, col: 6 },
+        { label: '中文隶属关系', key: 'affiliation_zh', type: 'text', outlined: true, dense: true, col: 6 },
+        { label: '英文隶属关系', key: 'affiliation_en', type: 'text', outlined: true, dense: true, col: 6 },
+        { label: '品牌组合', key: 'brand_group', type: 'text', outlined: true, dense: true, col: 6 },
+        { slotName: 'career_path', key: 'career_path' },
+        { slotName: 'addressInfo' },
+        { label: '中文地址', key: 'address_zh', type: 'text', outlined: true, dense: true, col: 6 },
+        { label: '英文地址', key: 'address_en', type: 'text', outlined: true, dense: true, col: 6 },
+        { label: '中文邮政编码', key: 'postal_code_zh', type: 'text', outlined: true, dense: true, col: 6 },
+        { label: '英文邮政编码', key: 'postal_code_en', type: 'text', outlined: true, dense: true, col: 6 },
+        { slotName: 'systemInfo' }
+      ],
+      formQuery: {},
+      id: null,
+      itemData: null
+    }
+  },
+  methods: {
+    async open (item) {
+      this.show = true
+      this.loading = false
+      this.itemData = null
+      const defaultCareer = {
+        company_name: null,
+        position: null
+      }
+      this.formQuery = this.formItems.reduce((res, val) => {
+        if (val.key) {
+          res[val.key] = val.key === 'career_path' ? [defaultCareer] : null
+        }
+        return res
+      }, {})
+      if (!item) {
+        this.file = null
+        this.previewUrl = null
+        this.id = null
+        this.formQuery.career_path = [defaultCareer]
+        return
+      }
+      this.id = item.id
+      this.itemData = { ...item }
+      Object.keys(this.formQuery).forEach(key => {
+        this.formQuery[key] = item[key] || (key === 'career_path' ? [defaultCareer] : null)
+      })
+      // 获取文件内容
+      if (!item.image_path) {
+        this.file = null
+        this.previewUrl = null
+        return
+      }
+      try {
+        const { data } = await getBusinessCardImage(item.image_path)
+        this.file = new File([data], item.image_path, { type: data.type })
+        this.previewUrl = URL.createObjectURL(data)
+      } catch (error) {
+        this.$snackbar.error(error)
+      }
+    },
+    async handleImport (file) {
+      this.loading = true
+      this.file = file
+      this.handlePreview(file, () => {
+        this.loading = false
+      })
+    },
+    handlePreview (file, cb) {
+      // 创建预览
+      const reader = new FileReader()
+      reader.onload = (e) => {
+        this.previewUrl = e.target.result
+        cb()
+      }
+      reader.readAsDataURL(file)
+    },
+    async handleAnalysis () {
+      this.linearLoading = true
+      const query = new FormData()
+      query.append('image', this.file)
+      try {
+        const { data } = await businessCardParse(query)
+        this.id = data.id
+        this.itemData = { ...data }
+        Object.keys(this.formQuery).forEach(key => {
+          this.formQuery[key] = data[key] || null
+        })
+        this.$snackbar.success('名片解析成功')
+      } catch (error) {
+        this.$snackbar.error(error)
+      } finally {
+        this.linearLoading = false
+      }
+    },
+    addCareerPath () {
+      this.formQuery.career_path = this.formQuery.career_path || []
+      this.formQuery.career_path.push({
+        company_name: null,
+        position: null
+      })
+    },
+    removeCareerPath (index) {
+      if (this.formQuery.career_path && this.formQuery.career_path.length > index) {
+        this.formQuery.career_path.splice(index, 1)
+      }
+    },
+    async handleUpdate () {
+      if (!this.id) {
+        this.$snackbar.error('ID获取异常')
+        return
+      }
+      Object.assign(this.itemData, this.formQuery)
+      try {
+        await updateBusinessCard(this.itemData, this.id)
+        this.$snackbar.success('更新成功')
+      } catch (error) {
+        this.$snackbar.error(error)
+      }
+    },
+    handleClose () {
+      if (!this.id) {
+        return
+      }
+      this.$emit('refresh')
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.fullBox {
+  width: 100%;
+  height: 100%;
+  min-height: 400px;
+}
+.upload-card {
+  // position: relative;
+  .change {
+    position: sticky;
+    top: 0;
+  }
+
+}
+.box-1 {
+  display: grid;
+  grid-template-columns: 1fr;
+  &.box-2 {
+    grid-template-columns: 1fr 1fr;
+    grid-gap: 15px;
+  }
+}
+
+.infoBox {
+  .label {
+    width: 100px;
+    display: inline-block;
+    text-align: right;
+    margin-right: 10px;
+    color: #666;
+  }
+}
+</style>

+ 135 - 0
src/views/menduner/system/talentMap/components/card.vue

@@ -0,0 +1,135 @@
+<template>
+  <ContentWrap>
+    <!-- 搜索工作栏 -->
+    <el-form
+      class="-mb-15px"
+      :model="queryParams"
+      ref="queryFormRef"
+      :inline="true"
+      label-width="68px"
+    >
+      <el-form-item label="名称" prop="name">
+        <el-input v-model="queryParams.email" placeholder="请输入名称" clearable @keyup.enter="handleQuery" class="!w-180px" />
+      </el-form-item>
+      <!-- <el-form-item label="选择" prop="sex">
+        <el-select v-model="queryParams.sex" placeholder="请选择选择" class="!w-180px">
+          <el-option v-for="dict in getIntDictOptions(DICT_TYPE.MENDUNER_SEX)" :key="dict.value" :label="dict.label" :value="dict.value"/>
+        </el-select>
+      </el-form-item> -->
+      <el-form-item>
+        <el-button @click="handleQuery"><Icon icon="ep:search" /> 搜索</el-button>
+        <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
+        <el-button type="primary" plain @click="handleAdd">
+          <Icon icon="ep:plus" class="mr-5px" /> 新增解析
+        </el-button>
+      </el-form-item>
+    </el-form>
+  </ContentWrap>
+
+  <!-- 列表 -->
+  <ContentWrap>
+    <el-table v-loading="loading" :data="list" :stripe="true">
+      <el-table-column label="姓名(中)" align="center" prop="person.name_zh" fixed="left" />
+      <el-table-column label="姓名(英)" align="center" prop="person.name_en" />
+      <el-table-column label="职位" align="center" prop="person.title_en" />
+      <el-table-column label="酒店/公司" align="center" prop="person.hotel_zh" />
+      <el-table-column label="创建日期" align="center" prop="person.created_at" :formatter="dateFormatter2" />
+      <el-table-column label="状态" align="center" prop="person.status" />
+      <el-table-column label="操作" align="center" fixed="right" min-width="110">
+        <template #default="scope">
+          <el-button link type="primary" @click="handleEdit(scope.row.person.id)">编辑</el-button>
+          <el-button link type="danger" @click="handleDisable(scope.row.person.id)">禁用</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    <!-- 分页 -->
+    <Pagination
+      :total="total"
+      v-model:page="queryParams.pageNo"
+      v-model:limit="queryParams.pageSize"
+      @pagination="getList"
+    />
+  </ContentWrap>
+</template>
+
+<script setup>
+import { TalentMap } from '@/api/menduner/system/talentMap'
+import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
+import { getDict } from '@/hooks/web/useDictionaries'
+import { dateFormatter, dateFormatter2 } from '@/utils/formatTime'
+
+/** 人才地图 列表 */
+defineOptions({ name: 'TalentMap' })
+
+const message = useMessage() // 消息弹窗
+const { t } = useI18n() // 国际化
+
+const loading = ref(false) // 列表的加载中
+const list = ref([]) // 列表的数据
+const total = ref(0) // 列表的总页数
+const queryParams = reactive({
+  pageNo: 1,
+  pageSize: 10,
+  name: undefined,
+  phone: undefined,
+  sex: undefined,
+  email: undefined,
+  eduType: undefined,
+  expType: undefined,
+  areaId: undefined,
+})
+const queryFormRef = ref() // 搜索的表单
+
+/** 查询列表 */
+const getList = async () => {
+  loading.value = true
+  try {
+    const data = await TalentMap.getTalentMapInfoPage(queryParams)
+    list.value = data.list
+    total.value = data.total
+  } finally {
+    loading.value = false
+  }
+}
+
+/** 搜索按钮操作 */
+const handleQuery = () => {
+  queryParams.pageNo = 1
+  getList()
+}
+
+/** 重置按钮操作 */
+const resetQuery = () => {
+  queryFormRef.value.resetFields()
+  handleQuery()
+}
+
+/** 编辑 */
+const { push } = useRouter()
+const handleEdit = (id) => {
+  push({ name: 'ImageImportEdit', params: { id } })
+}
+
+/** 禁用按钮操作 */
+const handleDisable = async (id) => {
+  if (!id) return message.warning('禁用失败,请稍后再试')
+  try {
+    // 禁用的二次确认
+    await message.delConfirm()
+    // 发起禁用
+    await TalentMap.deleteTalentMap(id)
+    message.success(t('common.delSuccess'))
+    // 刷新列表
+    await getList()
+  } catch {}
+}
+
+const handleAdd = () => {
+  push({ name: 'TalentMapDetail', params: { id: 'add' } })
+}
+
+/** 初始化 **/
+onMounted(() => {
+  getList()
+})
+</script>

+ 188 - 0
src/views/menduner/system/talentMap/components/resume.vue

@@ -0,0 +1,188 @@
+<template>
+  <ContentWrap>
+    <!-- 搜索工作栏 -->
+    <el-form
+      class="-mb-15px"
+      :model="queryParams"
+      ref="queryFormRef"
+      :inline="true"
+      label-width="68px"
+    >
+      <el-form-item label="姓名" prop="name">
+        <el-input v-model="queryParams.name" placeholder="请输入姓名" clearable @keyup.enter="handleQuery" class="!w-180px" />
+      </el-form-item>
+      <el-form-item label="联系电话" prop="phone">
+        <el-input v-model="queryParams.phone" placeholder="请输入联系电话" clearable @keyup.enter="handleQuery" class="!w-180px" />
+      </el-form-item>
+      <el-form-item label="邮箱" prop="email">
+        <el-input v-model="queryParams.email" placeholder="请输入邮箱" clearable @keyup.enter="handleQuery" class="!w-180px" />
+      </el-form-item>
+      <el-form-item label="性别" prop="sex">
+        <el-select v-model="queryParams.sex" placeholder="请选择性别" class="!w-180px">
+          <el-option v-for="dict in getIntDictOptions(DICT_TYPE.MENDUNER_SEX)" :key="dict.value" :label="dict.label" :value="dict.value"/>
+        </el-select>
+      </el-form-item>
+      <el-form-item label="学历" prop="eduType">
+        <el-select v-model="queryParams.eduType" placeholder="请选择学历" class="!w-180px">
+          <el-option v-for="dict in getIntDictOptions(DICT_TYPE.MENDUNER_EDUCATION_TYPE)" :key="dict.value" :label="dict.label" :value="dict.value" />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="工作经验" prop="expType">
+        <el-select v-model="queryParams.expType" placeholder="请选择工作经验" class="!w-180px">
+          <el-option v-for="dict in getIntDictOptions(DICT_TYPE.MENDUNER_EXP_TYPE)" :key="dict.value" :label="dict.label" :value="dict.value" />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="所在城市" prop="areaId">
+        <el-cascader v-model="queryParams.areaId" :options="areaTreeData" :props="{ label: 'name', value: 'id', emitPath: false, checkStrictly: true }"  class="!w-180px" />
+      </el-form-item>
+      <el-form-item>
+        <el-button @click="handleQuery"><Icon icon="ep:search" /> 搜索</el-button>
+        <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
+        <el-button type="primary" plain @click="handleAdd">
+          <Icon icon="ep:plus" class="mr-5px" /> 新增人才
+        </el-button>
+      </el-form-item>
+    </el-form>
+  </ContentWrap>
+
+  <!-- 列表 -->
+  <ContentWrap>
+    <el-table v-loading="loading" :data="list" :stripe="true">
+      <el-table-column label="头像" align="center" prop="avatar" width="70px" fixed="left">
+        <template #default="scope">
+          <el-image v-if="scope.row?.person.avatar" class="h-60px w-60px" :src="scope.row?.person.avatar" lazy preview-teleported :preview-src-list="[scope.row?.person.avatar]" fit="contain" />
+        </template>
+      </el-table-column>
+      <el-table-column label="姓名" align="center" prop="person.name" fixed="left" />
+      <el-table-column label="联系电话" align="center" prop="person.phone" />
+      <el-table-column label="邮箱" align="center" prop="person.email" />
+      <el-table-column label="性别" align="center" prop="person.sexStr" />
+      <el-table-column label="出生日期" align="center" prop="person.birthday" :formatter="dateFormatter2" />
+      <el-table-column label="学历" align="center" prop="person.eduTypeStr" />
+      <el-table-column label="工作经验" align="center" prop="person.expTypeStr" />
+      <el-table-column label="所在城市" align="center" prop="person.areaStr" />
+      <el-table-column label="意向城市" align="center">
+        <template #default="scope">
+          {{ scope.row?.person?.interestedAreaStrList && scope.row?.person?.interestedAreaStrList.length ? scope.row?.person?.interestedAreaStrList.join(',') : '' }}
+        </template>
+      </el-table-column>
+      <el-table-column label="求职意向" align="center">
+        <template #default="scope">
+          {{ scope.row?.person?.jobInterestedList && scope.row?.person?.jobInterestedList.length ? scope.row?.person?.jobInterestedList.join(',') : '' }}
+        </template>
+      </el-table-column>
+      <el-table-column label="首次工作时间" align="center" prop="person.firstWorkTime" :formatter="dateFormatter2" />
+      <el-table-column label="创建时间" align="center" prop="person.createTime" :formatter="dateFormatter" />
+      <el-table-column label="操作" align="center" fixed="right" min-width="110">
+        <template #default="scope">
+          <el-button link type="primary" @click="openDetail(scope.row.person.id)">详情</el-button>
+          <el-button link type="danger" @click="handleDelete(scope.row.person.id)">删除</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    <!-- 分页 -->
+    <Pagination
+      :total="total"
+      v-model:page="queryParams.pageNo"
+      v-model:limit="queryParams.pageSize"
+      @pagination="getList"
+    />
+  </ContentWrap>
+</template>
+
+<script setup>
+import { TalentMap } from '@/api/menduner/system/talentMap'
+import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
+import { getDict } from '@/hooks/web/useDictionaries'
+import { dateFormatter, dateFormatter2 } from '@/utils/formatTime'
+
+/** 人才地图 列表 */
+defineOptions({ name: 'TalentMap' })
+
+const message = useMessage() // 消息弹窗
+const { t } = useI18n() // 国际化
+
+const loading = ref(false) // 列表的加载中
+const list = ref([]) // 列表的数据
+const total = ref(0) // 列表的总页数
+const queryParams = reactive({
+  pageNo: 1,
+  pageSize: 10,
+  name: undefined,
+  phone: undefined,
+  sex: undefined,
+  email: undefined,
+  eduType: undefined,
+  expType: undefined,
+  areaId: undefined,
+})
+const queryFormRef = ref() // 搜索的表单
+
+// 地区列表
+const areaTreeData = ref([])
+const getDictData = async () => {
+  const { data } = await getDict('areaTreeData', {}, 'areaTreeData')
+  const obj = data.find(e => e.name === '中国')
+  const list = obj?.children ? obj.children.map(e =>{
+    // 市辖区直接显示区
+    const municipality = e.children && e.children.length && e.children[0].name === '市辖区'
+    if (municipality && e.children[0].children?.length) e.children = e.children[0].children
+    return e
+  }) : []
+  areaTreeData.value = list.length ? list : []
+}
+getDictData()
+
+/** 查询列表 */
+const getList = async () => {
+  loading.value = true
+  try {
+    const data = await TalentMap.getTalentMapInfoPage(queryParams)
+    list.value = data.list
+    total.value = data.total
+  } finally {
+    loading.value = false
+  }
+}
+
+/** 搜索按钮操作 */
+const handleQuery = () => {
+  queryParams.pageNo = 1
+  getList()
+}
+
+/** 重置按钮操作 */
+const resetQuery = () => {
+  queryFormRef.value.resetFields()
+  handleQuery()
+}
+
+/** 打开用户详情 */
+const { push } = useRouter()
+const openDetail = (id) => {
+  push({ name: 'TalentMapDetail', params: { id } })
+}
+
+/** 删除按钮操作 */
+const handleDelete = async (id) => {
+  if (!id) return message.warning('删除失败,请稍后再试')
+  try {
+    // 删除的二次确认
+    await message.delConfirm()
+    // 发起删除
+    await TalentMap.deleteTalentMap(id)
+    message.success(t('common.delSuccess'))
+    // 刷新列表
+    await getList()
+  } catch {}
+}
+
+const handleAdd = () => {
+  push({ name: 'TalentMapDetail', params: { id: 'add' } })
+}
+
+/** 初始化 **/
+onMounted(() => {
+  getList()
+})
+</script>

+ 16 - 181
src/views/menduner/system/talentMap/index.vue

@@ -1,188 +1,23 @@
 <template>
-  <ContentWrap>
-    <!-- 搜索工作栏 -->
-    <el-form
-      class="-mb-15px"
-      :model="queryParams"
-      ref="queryFormRef"
-      :inline="true"
-      label-width="68px"
-    >
-      <el-form-item label="姓名" prop="name">
-        <el-input v-model="queryParams.name" placeholder="请输入姓名" clearable @keyup.enter="handleQuery" class="!w-180px" />
-      </el-form-item>
-      <el-form-item label="联系电话" prop="phone">
-        <el-input v-model="queryParams.phone" placeholder="请输入联系电话" clearable @keyup.enter="handleQuery" class="!w-180px" />
-      </el-form-item>
-      <el-form-item label="邮箱" prop="email">
-        <el-input v-model="queryParams.email" placeholder="请输入邮箱" clearable @keyup.enter="handleQuery" class="!w-180px" />
-      </el-form-item>
-      <el-form-item label="性别" prop="sex">
-        <el-select v-model="queryParams.sex" placeholder="请选择性别" class="!w-180px">
-          <el-option v-for="dict in getIntDictOptions(DICT_TYPE.MENDUNER_SEX)" :key="dict.value" :label="dict.label" :value="dict.value"/>
-        </el-select>
-      </el-form-item>
-      <el-form-item label="学历" prop="eduType">
-        <el-select v-model="queryParams.eduType" placeholder="请选择学历" class="!w-180px">
-          <el-option v-for="dict in getIntDictOptions(DICT_TYPE.MENDUNER_EDUCATION_TYPE)" :key="dict.value" :label="dict.label" :value="dict.value" />
-        </el-select>
-      </el-form-item>
-      <el-form-item label="工作经验" prop="expType">
-        <el-select v-model="queryParams.expType" placeholder="请选择工作经验" class="!w-180px">
-          <el-option v-for="dict in getIntDictOptions(DICT_TYPE.MENDUNER_EXP_TYPE)" :key="dict.value" :label="dict.label" :value="dict.value" />
-        </el-select>
-      </el-form-item>
-      <el-form-item label="所在城市" prop="areaId">
-        <el-cascader v-model="queryParams.areaId" :options="areaTreeData" :props="{ label: 'name', value: 'id', emitPath: false, checkStrictly: true }"  class="!w-180px" />
-      </el-form-item>
-      <el-form-item>
-        <el-button @click="handleQuery"><Icon icon="ep:search" /> 搜索</el-button>
-        <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
-        <el-button type="primary" plain @click="handleAdd">
-          <Icon icon="ep:plus" class="mr-5px" /> 新增人才
-        </el-button>
-      </el-form-item>
-    </el-form>
-  </ContentWrap>
-
-  <!-- 列表 -->
-  <ContentWrap>
-    <el-table v-loading="loading" :data="list" :stripe="true">
-      <el-table-column label="头像" align="center" prop="avatar" width="70px" fixed="left">
-        <template #default="scope">
-          <el-image v-if="scope.row?.person.avatar" class="h-60px w-60px" :src="scope.row?.person.avatar" lazy preview-teleported :preview-src-list="[scope.row?.person.avatar]" fit="contain" />
-        </template>
-      </el-table-column>
-      <el-table-column label="姓名" align="center" prop="person.name" fixed="left" />
-      <el-table-column label="联系电话" align="center" prop="person.phone" />
-      <el-table-column label="邮箱" align="center" prop="person.email" />
-      <el-table-column label="性别" align="center" prop="person.sexStr" />
-      <el-table-column label="出生日期" align="center" prop="person.birthday" :formatter="dateFormatter2" />
-      <el-table-column label="学历" align="center" prop="person.eduTypeStr" />
-      <el-table-column label="工作经验" align="center" prop="person.expTypeStr" />
-      <el-table-column label="所在城市" align="center" prop="person.areaStr" />
-      <el-table-column label="意向城市" align="center">
-        <template #default="scope">
-          {{ scope.row?.person?.interestedAreaStrList && scope.row?.person?.interestedAreaStrList.length ? scope.row?.person?.interestedAreaStrList.join(',') : '' }}
-        </template>
-      </el-table-column>
-      <el-table-column label="求职意向" align="center">
-        <template #default="scope">
-          {{ scope.row?.person?.jobInterestedList && scope.row?.person?.jobInterestedList.length ? scope.row?.person?.jobInterestedList.join(',') : '' }}
-        </template>
-      </el-table-column>
-      <el-table-column label="首次工作时间" align="center" prop="person.firstWorkTime" :formatter="dateFormatter2" />
-      <el-table-column label="创建时间" align="center" prop="person.createTime" :formatter="dateFormatter" />
-      <el-table-column label="操作" align="center" fixed="right" min-width="110">
-        <template #default="scope">
-          <el-button link type="primary" @click="openDetail(scope.row.person.id)">详情</el-button>
-          <el-button link type="danger" @click="handleDelete(scope.row.person.id)">删除</el-button>
-        </template>
-      </el-table-column>
-    </el-table>
-    <!-- 分页 -->
-    <Pagination
-      :total="total"
-      v-model:page="queryParams.pageNo"
-      v-model:limit="queryParams.pageSize"
-      @pagination="getList"
-    />
-  </ContentWrap>
+  <div>
+		<el-tabs v-model="activeName" @tab-click="handleClick">
+			<el-tab-pane label="简历" name="resume">
+				<resumePage/>
+			</el-tab-pane>
+			<el-tab-pane label="名片" name="card">
+				<cardPage/>
+			</el-tab-pane>
+			<el-tab-pane label="网页" name="webpage">
+				<!-- <cardPage/> -->
+			</el-tab-pane>
+		</el-tabs>
+	</div>
 </template>
 
 <script setup>
-import { TalentMap } from '@/api/menduner/system/talentMap'
-import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
-import { getDict } from '@/hooks/web/useDictionaries'
-import { dateFormatter, dateFormatter2 } from '@/utils/formatTime'
-
-/** 人才地图 列表 */
 defineOptions({ name: 'TalentMap' })
+import resumePage from './components/resume.vue'
+import cardPage from './components/card.vue'
 
-const message = useMessage() // 消息弹窗
-const { t } = useI18n() // 国际化
-
-const loading = ref(false) // 列表的加载中
-const list = ref([]) // 列表的数据
-const total = ref(0) // 列表的总页数
-const queryParams = reactive({
-  pageNo: 1,
-  pageSize: 10,
-  name: undefined,
-  phone: undefined,
-  sex: undefined,
-  email: undefined,
-  eduType: undefined,
-  expType: undefined,
-  areaId: undefined,
-})
-const queryFormRef = ref() // 搜索的表单
-
-// 地区列表
-const areaTreeData = ref([])
-const getDictData = async () => {
-  const { data } = await getDict('areaTreeData', {}, 'areaTreeData')
-  const obj = data.find(e => e.name === '中国')
-  const list = obj?.children ? obj.children.map(e =>{
-    // 市辖区直接显示区
-    const municipality = e.children && e.children.length && e.children[0].name === '市辖区'
-    if (municipality && e.children[0].children?.length) e.children = e.children[0].children
-    return e
-  }) : []
-  areaTreeData.value = list.length ? list : []
-}
-getDictData()
-
-/** 查询列表 */
-const getList = async () => {
-  loading.value = true
-  try {
-    const data = await TalentMap.getTalentMapInfoPage(queryParams)
-    list.value = data.list
-    total.value = data.total
-  } finally {
-    loading.value = false
-  }
-}
-
-/** 搜索按钮操作 */
-const handleQuery = () => {
-  queryParams.pageNo = 1
-  getList()
-}
-
-/** 重置按钮操作 */
-const resetQuery = () => {
-  queryFormRef.value.resetFields()
-  handleQuery()
-}
-
-/** 打开用户详情 */
-const { push } = useRouter()
-const openDetail = (id) => {
-  push({ name: 'TalentMapDetail', params: { id } })
-}
-
-/** 删除按钮操作 */
-const handleDelete = async (id) => {
-  if (!id) return message.warning('删除失败,请稍后再试')
-  try {
-    // 删除的二次确认
-    await message.delConfirm()
-    // 发起删除
-    await TalentMap.deleteTalentMap(id)
-    message.success(t('common.delSuccess'))
-    // 刷新列表
-    await getList()
-  } catch {}
-}
-
-const handleAdd = () => {
-  push({ name: 'TalentMapDetail', params: { id: 'add' } })
-}
-
-/** 初始化 **/
-onMounted(() => {
-  getList()
-})
+const activeName = ref('resume')
 </script>