123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306 |
- <template>
- <m-dialog title="名片解析" :visible.sync="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 #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="success">开启</v-chip>
- </div>
- <div class="mb-3">
- <span class="label">创建时间</span>
- <v-chip small color="info">2025/03/31 10:06</v-chip>
- </div>
- <div class="mb-3">
- <span class="label">更新时间</span>
- <v-chip small color="info">2025/03/31 11:48</v-chip>
- </div>
- </div>
- </div>
- </template>
- </MForm>
- </div>
- </MCard>
- </div>
- <Linear text="解析中..." :visible.sync="linearLoading"></Linear>
- </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 },
- { label: '职业轨迹', key: 'career_path', type: 'text', outlined: true, dense: true, col: 6 },
- { 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
- this.formQuery = this.formItems.reduce((res, val) => {
- if (val.key) {
- res[val.key] = null
- }
- return res
- }, {})
- if (!item) {
- this.file = null
- this.previewUrl = null
- this.id = null
- return
- }
- this.id = item.id
- this.itemData = { ...item }
- Object.keys(this.formQuery).forEach(key => {
- this.formQuery[key] = item[key] || 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
- }
- },
- 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>
|