Browse Source

feat: ✨ 个人中心,详情,修复时间问题

@sun-chaoqun 2 years ago
parent
commit
adf7683598

+ 7 - 0
components.d.ts

@@ -19,9 +19,13 @@ declare module '@vue/runtime-core' {
     ElBreadcrumbItem: typeof import('element-plus/es')['ElBreadcrumbItem']
     ElButton: typeof import('element-plus/es')['ElButton']
     ElCard: typeof import('element-plus/es')['ElCard']
+    ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
+    ElCheckboxGroup: typeof import('element-plus/es')['ElCheckboxGroup']
     ElCol: typeof import('element-plus/es')['ElCol']
     ElContainer: typeof import('element-plus/es')['ElContainer']
     ElDatePicker: typeof import('element-plus/es')['ElDatePicker']
+    ElDescriptions: typeof import('element-plus/es')['ElDescriptions']
+    ElDescriptionsItem: typeof import('element-plus/es')['ElDescriptionsItem']
     ElDialog: typeof import('element-plus/es')['ElDialog']
     ElDivider: typeof import('element-plus/es')['ElDivider']
     ElDrawer: typeof import('element-plus/es')['ElDrawer']
@@ -40,6 +44,8 @@ declare module '@vue/runtime-core' {
     ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
     ElOption: typeof import('element-plus/es')['ElOption']
     ElPagination: typeof import('element-plus/es')['ElPagination']
+    ElRadio: typeof import('element-plus/es')['ElRadio']
+    ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup']
     ElRow: typeof import('element-plus/es')['ElRow']
     ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
     ElSelect: typeof import('element-plus/es')['ElSelect']
@@ -47,6 +53,7 @@ declare module '@vue/runtime-core' {
     ElTable: typeof import('element-plus/es')['ElTable']
     ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
     ElTag: typeof import('element-plus/es')['ElTag']
+    ElText: typeof import('element-plus/es')['ElText']
     ElTooltip: typeof import('element-plus/es')['ElTooltip']
     ElUpload: typeof import('element-plus/es')['ElUpload']
     Loading: typeof import('./src/components/Loading/index.vue')['default']

+ 11 - 0
package-lock.json

@@ -9,6 +9,7 @@
       "version": "0.0.0",
       "dependencies": {
         "@element-plus/icons-vue": "^2.1.0",
+        "animate.css": "^4.1.1",
         "axios": "^1.3.4",
         "dayjs": "^1.11.7",
         "el-table-infinite-scroll": "^3.0.1",
@@ -1663,6 +1664,11 @@
         "uri-js": "^4.2.2"
       }
     },
+    "node_modules/animate.css": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmmirror.com/animate.css/-/animate.css-4.1.1.tgz",
+      "integrity": "sha512-+mRmCTv6SbCmtYJCN4faJMNFVNN5EuCTTprDTAo7YzIGji2KADmakjVA3+8mVDkZ2Bf09vayB35lSQIex2+QaQ=="
+    },
     "node_modules/ansi-regex": {
       "version": "5.0.1",
       "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz",
@@ -5676,6 +5682,11 @@
         "uri-js": "^4.2.2"
       }
     },
+    "animate.css": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmmirror.com/animate.css/-/animate.css-4.1.1.tgz",
+      "integrity": "sha512-+mRmCTv6SbCmtYJCN4faJMNFVNN5EuCTTprDTAo7YzIGji2KADmakjVA3+8mVDkZ2Bf09vayB35lSQIex2+QaQ=="
+    },
     "ansi-regex": {
       "version": "5.0.1",
       "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz",

+ 1 - 0
package.json

@@ -10,6 +10,7 @@
   },
   "dependencies": {
     "@element-plus/icons-vue": "^2.1.0",
+    "animate.css": "^4.1.1",
     "axios": "^1.3.4",
     "dayjs": "^1.11.7",
     "el-table-infinite-scroll": "^3.0.1",

+ 2 - 0
src/api/user/index.ts

@@ -15,3 +15,5 @@ export const User_Dept_List = (params?: any) => $http.post('/api/user/Dept/List'
 export const User_Post_List = (params?: any) => $http.post('/api/user/Post/List', params)
 // 用户信息
 export const User_Info = (params?: any) => $http.post('/api/user/User/Info', params)
+// 修改密码
+export const User_Post = (params?: any) => $http.post('/api/user/User/Post', params)

+ 10 - 16
src/components/Upload/index.vue

@@ -1,10 +1,9 @@
 <script setup lang="ts">
 import { ref, watch } from 'vue'
-// import { Plus } from '@element-plus/icons-vue'
 import { UpFileToken } from '@/api/public/index'
 import { ElMessage, genFileId, ElLoading } from 'element-plus'
 import { GlobalStore } from '@/stores/index'
-import type { UploadProps, UploadRawFile, UploadUserFile, UploadFile, UploadFiles } from 'element-plus'
+import type { UploadProps, UploadRawFile, UploadFile, UploadFiles } from 'element-plus'
 
 interface FileListType {
   url?: string
@@ -12,12 +11,14 @@ interface FileListType {
 }
 
 interface ProTableProps {
-  isImg?: boolean // 是否只能上传图片
+  // isImg?: boolean // 是否只能上传图片
   disabled?: boolean
   limit: number
   accept: string
   modelValue: string | string[]
   listType?: string
+  errorText?: string
+  successText?: string
 }
 
 const upload = ref()
@@ -38,11 +39,6 @@ const handlePictureCardPreview = async (file: any) => {
 }
 // 图片上传之前
 const beforeUpload = async (file: any) => {
-  // let reg = /^image/g
-  // if (isImg.value && !reg.test(file.type)) {
-  //   ElMessage.error('必须上传图片!!')
-  //   return
-  // }
   loadingInstance = ElLoading.service({
     lock: true,
     text: 'Loading',
@@ -54,9 +50,7 @@ const beforeUpload = async (file: any) => {
   uploadData.key = file.name
 }
 // 图片上传超出界限
-const handleExceed: UploadProps['onExceed'] = (files: any, uploadFiles: UploadUserFile[]) => {
-  console.log(files, uploadFiles)
-
+const handleExceed: UploadProps['onExceed'] = (files: any) => {
   upload.value.clearFiles()
   const file = files[0] as UploadRawFile
   file.uid = genFileId()
@@ -72,12 +66,12 @@ const onSuccess = (response: any, uploadFile: UploadFile, uploadFiles: UploadFil
     let keys = uploadFiles.map((item: any) => ERPOSS + item.response.key)
     emit('update:modelValue', keys)
   }
-  ElMessage.success('图片上传成功!!')
+  ElMessage.success(props.successText)
   loadingInstance.close()
 }
 // 图片上传失败
 const onError = () => {
-  ElMessage.error('图片上传失败!!')
+  ElMessage.error(props.errorText)
 }
 // 图片移除
 const handleRemove: UploadProps['onRemove'] = (uploadFile: any, uploadFiles: UploadFiles) => {
@@ -96,7 +90,9 @@ const handleRemove: UploadProps['onRemove'] = (uploadFile: any, uploadFiles: Upl
 // 接受父组件参数,配置默认值
 const props = withDefaults(defineProps<ProTableProps>(), {
   disabled: false,
-  listType: 'picture-card'
+  listType: 'picture-card',
+  errorText: '图片上传失败!!',
+  successText: '图片上传成功!!'
 })
 
 const fileList = ref<FileListType[]>([])
@@ -152,8 +148,6 @@ defineExpose({
       :data="uploadData"
     >
       <slot></slot>
-      <!-- <el-button type="primary">Click to upload</el-button>
-      <el-icon><Plus /></el-icon> -->
       <template #tip>
         <div class="el-upload__tip">
           <slot name="tip"></slot>

+ 1 - 1
src/components/dialog/Dialog.vue

@@ -2,7 +2,7 @@
 import { ref } from 'vue'
 const dialogVisible = ref(false)
 interface DialogProps {
-  width: string
+  width?: string
 }
 withDefaults(defineProps<DialogProps>(), {
   width: '50%'

+ 3 - 1
src/layouts/Header/Breadcrumb.vue

@@ -8,7 +8,9 @@ const route = useRoute()
 const router = useRouter()
 
 const breadcrumbList: any = computed(() => {
-  return route.matched
+  return route.matched.reduce((all: any, next: any) => {
+    return all.some((item: any) => item['path'] == next['path']) ? all : [...all, next]
+  }, [])
 })
 // console.log(breadcrumbList)
 const isUnicode = (val: string | undefined) => {

+ 4 - 3
src/layouts/Header/index.vue

@@ -1,5 +1,5 @@
 <script setup lang="ts">
-import { ref} from 'vue'
+import { ref } from 'vue'
 import { useRouter } from 'vue-router'
 import { GlobalStore } from '@/stores/index'
 import Breadcrumb from './Breadcrumb.vue'
@@ -15,7 +15,7 @@ const logOut = () => {
   router.replace('/login')
 }
 
-const getTime = ()=>{
+const getTime = () => {
   return new Date().toLocaleString('en-US', {
     hour: 'numeric',
     minute: 'numeric',
@@ -72,11 +72,12 @@ setInterval(() => {
           <template #dropdown>
             <el-dropdown-menu>
               <el-dropdown-item @click="logOut">退出登录</el-dropdown-item>
+              <el-dropdown-item @click="router.push('/user')">个人中心</el-dropdown-item>
             </el-dropdown-menu>
           </template>
         </el-dropdown>
       </el-col>
-      <el-col :xl="2" :sm="3" class="notice">{{time}}</el-col>
+      <el-col :xl="2" :sm="3" class="notice">{{ time }}</el-col>
     </el-row>
   </div>
 </template>

+ 1 - 0
src/main.ts

@@ -1,6 +1,7 @@
 import { createApp } from 'vue'
 // 全局默认样式
 import './style.scss'
+import 'animate.css'
 // 进度条样式
 import 'nprogress/nprogress.css'
 // element-ui样式

+ 44 - 1
src/router/modules/staticRouter.ts

@@ -48,9 +48,52 @@ export const staticRouter: RouteRecordRaw[] = [
       {
         path: '/contract',
         name: 'Contract',
-        component: () => import('@/views/storehouse/sales/Contract.vue'),
+        component: () => import('@/views/storehouse/sales/index.vue'),
+        redirect: '/contract',
         meta: {
           title: '合同管理'
+        },
+        children: [
+          {
+            path: '/contract',
+            name: 'Contract',
+            component: () => import('@/views/storehouse/sales/Contract.vue'),
+            meta: {
+              title: '合同管理'
+            }
+          },
+          {
+            path: '/contract-detail/:id',
+            name: 'ContractDetail',
+            component: () => import('@/views/storehouse/sales/ContractDetail.vue'),
+            meta: {
+              title: '合同详情'
+            }
+          }
+        ]
+      },
+      // {
+      //   path: '/contract',
+      //   name: 'Contract',
+      //   component: () => import('@/views/storehouse/sales/Contract.vue'),
+      //   meta: {
+      //     title: '合同管理'
+      //   }
+      // },
+      // {
+      //   path: '/contract-detail/:id',
+      //   name: 'ContractDetail',
+      //   component: () => import('@/views/storehouse/sales/ContractDetail.vue'),
+      //   meta: {
+      //     title: '合同详情'
+      //   }
+      // },
+      {
+        path: '/user',
+        name: 'User',
+        component: () => import('@/views/home/User.vue'),
+        meta: {
+          title: '个人中心'
         }
       }
     ]

+ 4 - 4
src/views/account/users/Users.vue

@@ -99,19 +99,19 @@ const SearchInfo = () => {
       </template>
       <template #T_name="{ row }">{{ row.T_name }}</template>
       <template #T_sex="{ row }">
-        <el-tag class="ml-2" type="primary" v-if="row.T_sex === 1">男</el-tag>
+        <el-tag class="ml-2" v-if="row.T_sex === 1">男</el-tag>
         <el-tag class="ml-2" type="danger" v-else>女</el-tag>
       </template>
       <template #T_expire="{ row }">
-        <el-tag class="ml-2" type="primary" v-if="row.T_expire === 0">否</el-tag>
+        <el-tag class="ml-2" v-if="row.T_expire === 0">否</el-tag>
         <el-tag class="ml-2" type="danger" v-else>是</el-tag>
       </template>
       <template #T_marry="{ row }">
-        <el-tag class="ml-2" type="primary" v-if="row.T_marry === 0">未婚</el-tag>
+        <el-tag class="ml-2" v-if="row.T_marry === 0">未婚</el-tag>
         <el-tag class="ml-2" type="danger" v-else>已婚</el-tag>
       </template>
       <template #T_entry_type="{ row }">
-        <el-tag class="ml-2" type="primary" v-if="+row.T_entry_type === 1">全职</el-tag>
+        <el-tag class="ml-2" v-if="+row.T_entry_type === 1">全职</el-tag>
         <el-tag class="ml-2" type="warning" v-else-if="+row.T_entry_type === 2">兼职</el-tag>
         <el-tag class="ml-2" type="danger" v-else>实习生</el-tag>
       </template>

+ 227 - 0
src/views/home/User.vue

@@ -0,0 +1,227 @@
+<script setup lang="ts">
+import { fnMd5 } from '@/utils/common'
+import { useRouter } from 'vue-router'
+import { ElMessage } from 'element-plus'
+import { GlobalStore } from '@/stores/index'
+import { User_Post } from '@/api/user/index'
+import { View, Hide } from '@element-plus/icons-vue'
+import Dialog from '@/components/dialog/Dialog.vue'
+import { ref, computed, reactive, nextTick } from 'vue'
+import type { FormInstance, FormRules } from 'element-plus'
+
+const router = useRouter()
+const ruleFormRef = ref<FormInstance>()
+const globalStore = GlobalStore()
+const info = computed(() => globalStore.GET_User_Info)
+const dialogRef = ref<InstanceType<typeof Dialog> | null>(null)
+const getPlaceholder = (str: string | number): string | number => {
+  if (str || str === 0) return str
+  return '-'
+}
+const getT_entry_type = (str: string) => {
+  switch (str) {
+    case '1':
+      return '全职'
+    case '2':
+      return '兼职'
+    case '3':
+      return '实习生'
+  }
+}
+const getT_sex = (val: number) => {
+  if (!val) return val
+  switch (val) {
+    case 1:
+      return '男'
+    case 2:
+      return '女'
+  }
+}
+const getT_marryOrT_expire = (val: string | number, str: string) => {
+  if (val === '-') return val
+  switch (val) {
+    case 0:
+      return str === 'T_marry' ? '未婚' : '否'
+    case 1:
+      return str === 'T_marry' ? '未婚' : '是'
+  }
+}
+
+const ruleForm = reactive({
+  pass: '',
+  checkPass: ''
+})
+
+const validatePass = (rule: any, value: any, callback: any) => {
+  if (value === '') {
+    callback(new Error('请输入要修改的密码'))
+  } else {
+    if (ruleForm.checkPass !== '') {
+      if (!ruleFormRef.value) return
+      ruleFormRef.value.validateField('checkPass', () => null)
+    }
+    callback()
+  }
+}
+const validatePass2 = (rule: any, value: any, callback: any) => {
+  if (value === '') {
+    callback(new Error('请再一次输入要修改的密码'))
+  } else if (value !== ruleForm.pass) {
+    callback(new Error('两次密码不一致!'))
+  } else {
+    callback()
+  }
+}
+
+const rules = reactive<FormRules>({
+  pass: [{ validator: validatePass, trigger: 'blur' }],
+  checkPass: [{ validator: validatePass2, trigger: 'blur' }]
+})
+
+const submitForm = (formEl: FormInstance | undefined) => {
+  if (!formEl) return
+  formEl.validate(async valid => {
+    if (valid) {
+      const res: any = await User_Post({ User_tokey: globalStore.GET_User_tokey, T_pass: fnMd5(ruleForm.pass) })
+      console.log(res)
+      if (res.Code === 200) {
+        ElMessage.success('修改成功!!')
+        nextTick(() => resetForm(ruleFormRef.value))
+        logOut()
+      }
+    } else {
+      return false
+    }
+  })
+}
+
+const resetForm = (formEl: FormInstance | undefined) => {
+  if (!formEl) return
+  dialogRef.value?.DialogClose()
+  formEl.resetFields()
+}
+
+const logOut = () => {
+  localStorage.clear()
+  globalStore.SET_User_Tokey('')
+  globalStore.SET_User_Info({})
+  globalStore.SET_Flat_Menu([])
+  router.replace('/login')
+}
+
+const passType = ref('password')
+const checkPassType = ref('password')
+const changeType = (val: string) => {
+  if (val === 'pass') passType.value = passType.value === 'password' ? 'text' : 'password'
+  else checkPassType.value = checkPassType.value === 'password' ? 'text' : 'password'
+}
+</script>
+
+<template>
+  <div class="user">
+    <div class="info">
+      <h1>个人中心</h1>
+      <h3>宝智达: {{ getPlaceholder(info.T_name) }}</h3>
+      <div class="content">
+        <p>
+          用户名:<span>{{ getPlaceholder(info.T_user) }}</span>
+        </p>
+        <p>部门:{{ getPlaceholder(info.T_dept_name) }}</p>
+        <p>岗位:{{ getPlaceholder(info.T_post_name) }}</p>
+        <p>部门负责人:{{ info.T_dept_leader === 1 ? '是' : '否' }}</p>
+        <p>性别:{{ getT_sex(getPlaceholder(info.T_sex) as number) }}</p>
+        <p>民族:{{ getPlaceholder(info.T_nation) }}</p>
+        <p>毕业院校:{{ getPlaceholder(info.T_school) }}</p>
+        <p>专业:{{ getPlaceholder(info.T_major) }}</p>
+        <p>学历:{{ getPlaceholder(info.T_education) }}</p>
+        <p>联系电话:{{ getPlaceholder(info.T_phone) }}</p>
+        <p>婚否:{{ getT_marryOrT_expire(getPlaceholder(info.T_marry), 'T_marry') }}</p>
+        <p>配偶姓名:{{ getPlaceholder(info.T_spouse_name) }}</p>
+        <p>配偶联系电话:{{ getPlaceholder(info.T_spouse_phone) }}</p>
+        <p>入职时间:{{ getPlaceholder(info.T_entry_time) }}</p>
+        <p>转正时间:{{ getPlaceholder(info.T_positive_time) }}</p>
+        <p>入职类型:{{ getT_entry_type(getPlaceholder(info.T_entry_type) as string) }}</p>
+        <p>劳动合同开始时间:{{ getPlaceholder(info.T_contract_start_time) }}</p>
+        <p>劳动合同结束时间:{{ getPlaceholder(info.T_contract_end_time) }}</p>
+        <p>是否到期:{{ getT_marryOrT_expire(getPlaceholder(info.T_expire), 'T_expire') }}</p>
+        <p>备注:{{ getPlaceholder(info.T_remark) }}</p>
+      </div>
+      <div class="edit">
+        <el-button type="primary" @click="dialogRef?.DialogOpen()">修改密码</el-button>
+      </div>
+    </div>
+    <Dialog ref="dialogRef">
+      <template #header>
+        <h3>修改密码</h3>
+      </template>
+      <el-form ref="ruleFormRef" :model="ruleForm" :rules="rules" label-width="120px">
+        <el-form-item label="新密码" prop="pass">
+          <el-input v-model="ruleForm.pass" :type="passType" autocomplete="off">
+            <template #suffix>
+              <span class="view">
+                <el-icon v-if="passType === 'password'" class="el-input__icon" @click="changeType('pass')">
+                  <Hide />
+                </el-icon>
+                <el-icon v-else class="el-input__icon" @click="changeType('pass')">
+                  <View />
+                </el-icon>
+              </span>
+            </template>
+          </el-input>
+        </el-form-item>
+        <el-form-item label="确认密码" prop="checkPass">
+          <el-input v-model="ruleForm.checkPass" :type="checkPassType" autocomplete="off">
+            <template #suffix>
+              <span class="view">
+                <el-icon v-if="checkPassType === 'password'" class="el-input__icon" @click="changeType('checkPass')">
+                  <Hide />
+                </el-icon>
+                <el-icon v-else class="el-input__icon" @click="changeType('checkPass')">
+                  <View />
+                </el-icon>
+              </span>
+            </template>
+          </el-input>
+        </el-form-item>
+        <el-form-item>
+          <el-button @click="resetForm">取消</el-button>
+          <el-button type="primary" @click="submitForm(ruleFormRef)">确认</el-button>
+        </el-form-item>
+      </el-form>
+    </Dialog>
+  </div>
+</template>
+
+<style scoped lang="scss">
+.user {
+  // width: 100%;
+  height: 100%;
+  overflow-y: auto;
+  display: flex;
+  justify-content: center;
+  font-weight: bold;
+  color: var(--el-text-color-secondary);
+  .info {
+    padding: 20px;
+    // margin: 0px auto;
+    // white-space: nowrap;
+    // width: 20%;
+    h1 {
+      font-size: 32px;
+      margin-bottom: 2rem;
+    }
+    h3 {
+      font-size: 18px;
+    }
+    .content {
+      margin-top: 2rem;
+      span {
+        letter-spacing: 2px;
+      }
+    }
+    .edit {
+      margin-top: 2rem;
+    }
+  }
+}
+</style>

+ 13 - 1
src/views/storehouse/ProductionList.vue

@@ -33,7 +33,7 @@ const columns: ColumnProps[] = [
   { prop: 'T_model', label: '产品型号', ellipsis: true },
   { prop: 'T_spec', label: '产品规格' },
   { prop: 'T_relation_sn', label: '关联SN', name: 'T_relation_sn' },
-  { prop: 'T_remark', label: '备注' },
+  { prop: 'T_remark', label: '备注', name: 'T_remark' },
   { prop: 'operation', label: '操作', width: 150, fixed: 'right' }
 ]
 
@@ -214,6 +214,14 @@ onMounted(() => {
           </template>
         </el-image>
       </template>
+      <template #T_remark="{ row }">
+        <el-tooltip effect="customized" placement="left">
+          <template #content>
+            <div class="tooltip-content">{{ row.T_remark }}</div>
+          </template>
+          {{ row.T_remark }}
+        </el-tooltip>
+      </template>
       <template #T_relation_sn="{ row }">
         <el-tag v-if="row.T_relation_sn === 1" effect="dark">是</el-tag>
         <el-tag v-else type="success" effect="dark">否</el-tag>
@@ -278,6 +286,10 @@ onMounted(() => {
 </template>
 
 <style scoped lang="scss">
+.tooltip-content {
+  max-width: 500px;
+  overflow-y: auto;
+}
 .production-list {
   height: 100%;
   .el-image {

+ 14 - 5
src/views/storehouse/sales/Contract.vue

@@ -17,7 +17,7 @@ const columns: ColumnProps[] = [
   { prop: 'T_number', label: '合同编号' },
   { prop: 'T_customer', label: '客户名称' },
   { prop: 'T_State', label: '状态', name: 'T_State' },
-  { prop: 'T_out', label: '是否出库' },
+  { prop: 'T_out', label: '是否出库', name: 'T_out' },
   { prop: 'T_type', label: '更新时间' },
   { prop: 'operation', label: '操作', width: 260, fixed: 'right' }
 ]
@@ -26,6 +26,8 @@ const openContractFormDrawer = (type: string, row?: any) => {
   ContractFormRef.value?.openDrawer(type, row)
 }
 
+const updateOnTableList = () => TableRef.value?.getTableList()
+
 // 删除
 const UserDelete = (row: any) => {
   ElMessageBox.confirm('您确定要删除该物联网卡号吗?', '警告', {
@@ -93,9 +95,16 @@ const searchHandle = () => {
         </div>
       </template>
       <template #T_State="{ row }">
-        <el-tag v-if="row.T_State === 2" type="success" effect="dark"> 已使用 </el-tag>
-        <el-tag v-else-if="row.T_State === 1" type="warning" effect="dark"> 未使用 </el-tag>
-        <el-tag v-else type="info" effect="dark"> 已作废 </el-tag>
+        <el-tag v-if="row.T_State === 2" type="success" effect="dark"> 已通过 </el-tag>
+        <el-tag v-else-if="row.T_State === 1" type="warning" effect="dark"> 未通过 </el-tag>
+        <el-tag v-else type="danger" effect="dark"> 待审核 </el-tag>
+      </template>
+      <template #T_out="{ row }">
+        <el-tag v-if="row.T_out === 2 || row.T_out === 3" type="success" effect="dark">
+          {{ row.T_out === 2 ? '已出库' : '已全部出库' }}
+        </el-tag>
+        <el-tag v-else-if="row.T_State === 1" type="warning" effect="dark"> 未出库 </el-tag>
+        <el-tag v-else type="danger" effect="dark"> - </el-tag>
       </template>
       <template #right="{ row }">
         <el-button :disabled="row.T_State === 2" link type="warning" size="small" :icon="Finished">审核</el-button>
@@ -110,7 +119,7 @@ const searchHandle = () => {
         >
       </template>
     </TableBase>
-    <ContractForm ref="ContractFormRef" />
+    <ContractForm ref="ContractFormRef" @onTableList="updateOnTableList" />
   </div>
 </template>
 

+ 122 - 0
src/views/storehouse/sales/ContractDetail.vue

@@ -0,0 +1,122 @@
+<script setup lang="ts">
+import { ref } from 'vue'
+import { GlobalStore } from '@/stores/index'
+import { Storehouse_Contract_Get } from '@/api/storehouse/index'
+const info = ref({})
+const globalStore = GlobalStore()
+
+const getStorehouse_Contract_Get = async () => {
+  const res = await Storehouse_Contract_Get({ User_tokey: globalStore.GET_User_tokey, T_number: '6666666' })
+  console.log(res)
+}
+getStorehouse_Contract_Get()
+const columns = []
+
+const tableData = ref([])
+</script>
+
+<template>
+  <div class="contract-detail">
+    <div class="info">
+      <h1>详情 - <span>待审核</span></h1>
+
+      <div class="content">
+        <p>
+          <span>合同编号</span>
+          <span>BZD-123123123</span>
+        </p>
+        <p>
+          <span>客户名称</span>
+          <span>一树药业</span>
+        </p>
+        <p>
+          <span>合同类型</span>
+          <span>销售合同</span>
+        </p>
+        <p>
+          <span>产品明细</span>
+          <span>
+            <el-table
+              :data="tableData"
+              style="width: 100%"
+              border
+              stripe
+              :header-cell-style="{
+                background: '#909399',
+                height: '50px',
+                color: '#fff'
+              }"
+            >
+              <template v-for="item in columns" :key="item.prop">
+                <el-table-column v-bind="item" v-if="item.fixed !== 'right'">
+                  <template #default="{ row }" v-if="item.prop === item.name">
+                    <span v-if="item.prop === 'T_relation_sn'">
+                      <el-tag v-if="row.T_relation_sn === 1" effect="dark">是</el-tag>
+                      <el-tag v-else type="success" effect="dark">否</el-tag>
+                    </span>
+                    <el-image v-if="item.prop === 'T_img'" style="height: 50px" :src="row.T_img" fit="cover" />
+                  </template>
+                </el-table-column>
+                <el-table-column v-bind="item" v-if="item.fixed === 'right'">
+                  <el-button link type="danger" size="small">查看</el-button>
+                </el-table-column>
+              </template>
+            </el-table>
+          </span>
+        </p>
+      </div>
+    </div>
+    <!-- <el-table
+            :data="tableData"
+            style="width: 100%"
+            border
+            stripe
+            :header-cell-style="{
+              background: '#909399',
+              height: '50px',
+              color: '#fff'
+            }"
+          >
+            <template v-for="item in columns" :key="item.prop">
+              <el-table-column v-bind="item" v-if="item.fixed !== 'right'">
+                <template #header v-if="item.prop === 'count'">
+                  <span style="color: red">*数量</span>
+                </template>
+                <template #default="{ row }" v-if="item.prop === item.name">
+                  <el-input
+                    v-if="item.prop === 'count'"
+                    v-model.number="row.count"
+                    type="text"
+                    autocomplete="off"
+                    @blur="blurHandle"
+                  />
+                  <span v-if="item.prop === 'T_relation_sn'">
+                    <el-tag v-if="row.T_relation_sn === 1" effect="dark">是</el-tag>
+                    <el-tag v-else type="success" effect="dark">否</el-tag>
+                  </span>
+                  <el-image v-if="item.prop === 'T_img'" style="height: 50px" :src="row.T_img" fit="cover" />
+                </template>
+              </el-table-column>
+              <el-table-column v-bind="item" v-if="item.fixed === 'right'">
+                <el-button link type="danger" size="small" :icon="Delete">删除</el-button>
+              </el-table-column>
+            </template>
+            <template #append>
+              <el-button type="primary" @click="AddProductionDetailed">
+                <el-icon><Plus /></el-icon><span style="margin-left: 6px">添加产品</span>
+              </el-button>
+            </template>
+          </el-table> -->
+  </div>
+</template>
+
+<style scoped lang="scss">
+.contract-detail {
+  height: 100%;
+  font-weight: bold;
+  color: var(--el-text-color-secondary);
+  .info {
+    padding: 20px;
+  }
+}
+</style>

+ 45 - 24
src/views/storehouse/sales/ContractForm.vue

@@ -9,6 +9,7 @@ import { GlobalStore } from '@/stores/index'
 import TableBase from '@/components/TableBase/index.vue'
 import Upload from '@/components/Upload/index.vue'
 import {
+  Storehouse_Contract_Add,
   Storehouse_Product_List,
   Storehouse_IotCard_Edit,
   Storehouse_ProductClass_List,
@@ -27,12 +28,10 @@ const ruleFormRef = ref<FormInstance>()
 const drawerRef = ref<InstanceType<typeof Drawer> | null>(null)
 const dialogRef = ref<InstanceType<typeof Dialog> | null>(null)
 const uploadRef = ref<InstanceType<typeof Upload> | null>(null)
-const TableProductRef = ref<InstanceType<typeof TableBase> | null>(null)
+const selectTable = ref()
 const drawerProductRef = ref<InstanceType<typeof Drawer> | null>(null)
 
 const validate_T_product = (rule: any, value: any, callback: any) => {
-  console.log(value)
-
   if (form.T_type === 1 && value === '') {
     callback(new Error('请选择产品明细'))
   } else if (value.includes(undefined)) {
@@ -62,6 +61,9 @@ const resetForm = (formEl: FormInstance | undefined) => {
   formEl.resetFields()
 }
 
+// 父级方法
+const emit = defineEmits<{ (event: 'onTableList'): void }>()
+
 // 添加仓库名称
 interface FormType {
   T_id: string
@@ -100,19 +102,36 @@ const openDrawer = (type: string, row?: any) => {
   drawerRef.value?.openDrawer()
 }
 
-const AddContract = (formEl: FormInstance | undefined) => {
-  if (!formEl) return
+const blurHandle = () => {
   form.T_product = tableData.value.map(item => {
     if (!item.count) return undefined
     return `${item.Id},${item.count}`
   })
+}
+const deleteProduct = (id: number) => {
+  tableData.value = tableData.value.filter(item => item.Id !== id)
+  console.log(id)
+
+  selectTable.value?.toggleRowSelection([tableData.value[1]])
+}
+
+const AddContract = (formEl: FormInstance | undefined) => {
+  if (!formEl) return
+  // form.T_product = tableData.value.map(item => {
+  //   if (!item.count) return undefined
+  //   return `${item.Id},${item.count}`
+  // })
 
   formEl.validate(async valid => {
     if (valid) {
       let res: any = {}
       if (isNew.value) {
         console.log(form)
-        // res = await Storehouse_IotCard_Add({ User_tokey: globalStore.GET_User_tokey, ...form })
+        res = await Storehouse_Contract_Add({
+          ...form,
+          User_tokey: globalStore.GET_User_tokey,
+          T_product: form.T_product.toString()
+        })
       } else {
         res = await Storehouse_IotCard_Edit({
           User_tokey: globalStore.GET_User_tokey,
@@ -120,10 +139,10 @@ const AddContract = (formEl: FormInstance | undefined) => {
         })
       }
       if (res.Code === 200) {
-        ElMessage.success(`${isNew.value ? '添加' : '修改'}物联网卡成功!!`)
+        ElMessage.success(`${isNew.value ? '添加' : '修改'}合同成功!!`)
         nextTick(() => {
           drawerRef.value?.closeDrawer()
-          // TableRef.value?.getTableList()
+          emit('onTableList')
           resetForm(ruleFormRef.value)
           isNew.value = true
         })
@@ -154,7 +173,6 @@ const getProductClassList = async () => {
 // 获取产品型号
 const getProductModelList = async () => {
   const res: any = await Storehouse_Product_Model_List({ T_name: autoSelect.value })
-  console.log(res)
   modelOptions.value = res.Data.map((item: any, index: number) => {
     return {
       value: item,
@@ -167,22 +185,13 @@ const AddProductionDetailed = () => {
   !classOptions.value.length && getProductClassList()
   drawerProductRef.value?.openDrawer()
 }
-// 搜索名称
-const searchNameHandle = async () => {
-  console.log(initParam)
-  const res = await Storehouse_Product_Name_List({ T_name: initParam.T_name, T_class: initParam.T_class })
-  console.log(res)
-}
+
 // 搜索模型
 const searchModelHandle = () => {
   total = 0
   initParam.page = 1
   tableProductData.value = []
   getProductList()
-  // console.log(initParam)
-}
-const searchHandle = () => {
-  //
 }
 // 保存选中的数据id,row-key就是要指定一个key标识这一行的数据
 const getRowKey = (row: any) => {
@@ -205,7 +214,7 @@ const load = () => {
 let total = 0
 const tableProductData = ref<any[]>([])
 const getProductList = async () => {
-  const res: any = await Storehouse_Product_List({ ...initParam,T_name:  autoSelect.value})
+  const res: any = await Storehouse_Product_List({ ...initParam, T_name: autoSelect.value })
   console.log(res)
   tableProductData.value.push(...res.Data.Data)
   total = res.Data.Num
@@ -314,7 +323,13 @@ defineExpose({
                   <span style="color: red">*数量</span>
                 </template>
                 <template #default="{ row }" v-if="item.prop === item.name">
-                  <el-input v-if="item.prop === 'count'" v-model.number="row.count" type="text" autocomplete="off" />
+                  <el-input
+                    v-if="item.prop === 'count'"
+                    v-model.number="row.count"
+                    type="text"
+                    autocomplete="off"
+                    @blur="blurHandle"
+                  />
                   <span v-if="item.prop === 'T_relation_sn'">
                     <el-tag v-if="row.T_relation_sn === 1" effect="dark">是</el-tag>
                     <el-tag v-else type="success" effect="dark">否</el-tag>
@@ -323,7 +338,11 @@ defineExpose({
                 </template>
               </el-table-column>
               <el-table-column v-bind="item" v-if="item.fixed === 'right'">
-                <el-button link type="danger" size="small" :icon="Delete">删除</el-button>
+                <template #default="{ row }">
+                  <el-button link type="danger" size="small" :icon="Delete" @click="deleteProduct(row.Id)"
+                    >删除</el-button
+                  >
+                </template>
               </el-table-column>
             </template>
             <template #append>
@@ -358,11 +377,12 @@ defineExpose({
         </el-form-item>
         <el-form-item label="上传附件:" :label-width="formLabelWidth" prop="T_pdf">
           <Upload
+            v-model="form.T_pdf"
             class="w-50"
             ref="uploadRef"
-            :isImg="true"
             :limit="1"
-            v-model="form.T_pdf"
+            successText="文件上传成功!!"
+            errorText="文件上传失败"
             accept=".pdf"
             listType="text"
           >
@@ -420,6 +440,7 @@ defineExpose({
               </div>
             </template>
             <el-table
+              ref="selectTable"
               border
               :row-key="getRowKey"
               :data="tableProductData"

+ 7 - 0
src/views/storehouse/sales/index.vue

@@ -0,0 +1,7 @@
+<template>
+  <router-view></router-view>
+</template>
+
+<script setup lang="ts"></script>
+
+<style scoped></style>

+ 50 - 47
src/views/workAttendance/Leave.vue

@@ -56,10 +56,8 @@ const LeaveUser = async (T_State: number) => {
     } else {
       ElMessage.warning('审核不通过!')
     }
-    nextTick(() => {
-      TableRef.value.getTableList()
-      userInfo.value = {} as UserInfoIn
-    })
+    TableRef.value.getTableList()
+    userInfo.value = {} as UserInfoIn
   }
 }
 
@@ -96,50 +94,55 @@ onUnmounted(() => {
         </template>
       </TableBase>
     </div>
-    <el-row class="h-100 f-1 margin-left-3">
-      <el-col :span="24" class="h-100" style="overflow: hidden">
-        <el-card class="m-b-3 b-show-0">
-          <h3 class="title-user m-b-5">员工基本信息</h3>
-          <div class="info-content">
-            <el-avatar shape="square" size="large" :icon="UserFilled" />
-            <div class="info-name">
-              <h4 class="m-b-3">名字:{{ userInfo.T_user_name }}</h4>
+    <transition
+      leave-active-class="animate__animated animate__bounceOutRight"
+      enter-active-class="animate__animated animate__bounceInDown"
+    >
+      <el-row class="h-100 f-1 margin-left-3" v-if="userInfo.Id">
+        <el-col :span="24" class="h-100" style="overflow: hidden">
+          <el-card class="m-b-3 b-show-0">
+            <h3 class="title-user m-b-5">员工基本信息</h3>
+            <div class="info-content">
+              <el-avatar shape="square" size="large" :icon="UserFilled" />
+              <div class="info-name">
+                <h4 class="m-b-3">名字:{{ userInfo.T_user_name }}</h4>
+              </div>
             </div>
-          </div>
-        </el-card>
-        <el-card class="m-b-3 b-show-0" :style="{ height: cardHeight + 'px' }">
-          <el-descriptions title="请假申请" :column="1" size="large" border>
-            <el-descriptions-item label="请假类型:"
-              ><el-text class="mx-1" type="primary">{{
-                userInfo.T_type_name ? userInfo.T_type_name : '-'
-              }}</el-text></el-descriptions-item
-            >
-            <el-descriptions-item label="开始时间:"
-              ><el-text class="mx-1" type="primary">{{
-                userInfo.T_start_time ? userInfo.T_type_name : '-'
-              }}</el-text></el-descriptions-item
-            >
-            <el-descriptions-item label="结束时间:" :span="2"
-              ><el-text class="mx-1" type="primary">{{
-                userInfo.T_end_time ? userInfo.T_end_time : '-'
-              }}</el-text></el-descriptions-item
-            >
-            <el-descriptions-item label="请假时长:">
-              <el-text class="mx-1" type="primary">{{
-                userInfo.T_duration ? getFormatDuration(userInfo.T_duration) : '-'
-              }}</el-text>
-            </el-descriptions-item>
-            <el-descriptions-item label="内容:">
-              <el-text class="mx-1" type="primary">{{ userInfo.T_text ? userInfo.T_text : '-' }}</el-text>
-            </el-descriptions-item>
-          </el-descriptions>
-          <div class="btn">
-            <el-button type="primary" @click="LeaveUser(1)">通过</el-button>
-            <el-button type="danger" @click="LeaveUser(0)">不通过</el-button>
-          </div>
-        </el-card>
-      </el-col>
-    </el-row>
+          </el-card>
+          <el-card class="m-b-3 b-show-0" :style="{ height: cardHeight + 'px' }">
+            <el-descriptions title="请假申请" :column="1" size="large" border>
+              <el-descriptions-item label="请假类型:"
+                ><el-text class="mx-1" type="primary">{{
+                  userInfo.T_type_name ? userInfo.T_type_name : '-'
+                }}</el-text></el-descriptions-item
+              >
+              <el-descriptions-item label="开始时间:"
+                ><el-text class="mx-1" type="primary">{{
+                  userInfo.T_start_time ? userInfo.T_type_name : '-'
+                }}</el-text></el-descriptions-item
+              >
+              <el-descriptions-item label="结束时间:" :span="2"
+                ><el-text class="mx-1" type="primary">{{
+                  userInfo.T_end_time ? userInfo.T_end_time : '-'
+                }}</el-text></el-descriptions-item
+              >
+              <el-descriptions-item label="请假时长:">
+                <el-text class="mx-1" type="primary">{{
+                  userInfo.T_duration ? getFormatDuration(userInfo.T_duration) : '-'
+                }}</el-text>
+              </el-descriptions-item>
+              <el-descriptions-item label="内容:">
+                <el-text class="mx-1" type="primary">{{ userInfo.T_text ? userInfo.T_text : '-' }}</el-text>
+              </el-descriptions-item>
+            </el-descriptions>
+            <div class="btn">
+              <el-button type="primary" @click="LeaveUser(1)">通过</el-button>
+              <el-button type="danger" @click="LeaveUser(0)">不通过</el-button>
+            </div>
+          </el-card>
+        </el-col>
+      </el-row>
+    </transition>
   </div>
 </template>
 

+ 1 - 2
src/views/workAttendance/MyLeave.vue

@@ -92,7 +92,6 @@ const AddLeave = (formEl: FormInstance | undefined) => {
         ElMessage.warning('请假时长不得大于剩余时长,请重新选择时间!!')
         return
       }
-      console.log(form)
       if (isNew) {
         res = await Leave_Add({ ...form.value, T_approver: uuid, T_duration: time })
       } else {
@@ -205,7 +204,7 @@ onMounted(() => {
         <el-tag v-else type="danger">待审核</el-tag>
       </template>
       <template #T_duration="{ row }">
-        <el-tag effect="dark"> {{ row.T_duration }}分钟 </el-tag>
+        <el-tag effect="dark"> {{ getFormatDuration(row.T_duration) }} </el-tag>
       </template>
       <template #right="{ row }">
         <el-button link type="primary" size="small" :icon="Edit" @click="openDrawerLeave('edit', row)">编辑</el-button>

+ 10 - 89
src/views/workAttendance/MyOvertime.vue

@@ -8,7 +8,6 @@ import {
 } from '@/api/workAttendance/index'
 import { User_List } from '@/api/user/index'
 import { GlobalStore } from '@/stores/index'
-import { UpFileToken } from '@/api/public/index'
 import Drawer from '@/components/Drawer/index.vue'
 import Dialog from '@/components/dialog/Dialog.vue'
 import { floatReg } from '@/views/salary/salary/relus'
@@ -16,9 +15,10 @@ import { reactive, ref, nextTick } from 'vue'
 import TableBase from '@/components/TableBase/index.vue'
 import { getFormatDuration } from '@/utils/common'
 import { Edit, Delete, View, Plus } from '@element-plus/icons-vue'
-import { ElMessageBox, ElMessage, genFileId } from 'element-plus'
+import { ElMessageBox, ElMessage } from 'element-plus'
 import { ColumnProps } from '@/components/TableBase/interface/index'
-import type { FormInstance, FormRules, UploadProps, UploadRawFile } from 'element-plus'
+import type { FormInstance, FormRules } from 'element-plus'
+import Upload from '@/components/Upload/index.vue'
 
 let uuid = ''
 let isNew = true
@@ -32,6 +32,7 @@ const ruleFormRef = ref<FormInstance>()
 const dialog = ref<InstanceType<typeof Dialog> | null>(null)
 const drawerRef = ref<InstanceType<typeof Drawer> | null>(null)
 const TableRef = ref<InstanceType<typeof TableBase> | null>(null)
+const uploadRef = ref<InstanceType<typeof Upload> | null>(null)
 const initParam = { User_tokey: globalStore.GET_User_tokey }
 
 const columns: ColumnProps[] = [
@@ -58,11 +59,7 @@ const openDrawerOvertime = (str: string, row: any) => {
       uuid = row.T_approver
       form.value.T_approver = row.T_user_name
       form.value.T_id = row.Id
-      form.value.T_prove_img = import.meta.env.VITE_BZD_ERPOSS_APP_API + form.value.T_prove_img
-      fileList.value.push({
-        name: 'food.jpeg',
-        url: form.value.T_prove_img
-      })
+      form.value.T_duration = row.T_duration / 60
     })
   }
 }
@@ -96,18 +93,14 @@ const OvertimeDelete = (row: any) => {
 }
 const AddOvertime = (formEl: FormInstance | undefined) => {
   if (!formEl) return
-  if (!prove_img) {
-    ElMessage.warning('请等待图片上传完成')
-    return
-  }
   formEl.validate(async valid => {
     if (valid) {
       let res: any = {}
-      form.value.T_duration = form.value.T_duration * 60
+      let time = form.value.T_duration * 60
       if (isNew) {
-        res = await Overtime_Add({ ...form.value, T_approver: uuid })
+        res = await Overtime_Add({ ...form.value, T_approver: uuid, T_duration: time })
       } else {
-        res = await Overtime_Edit({ ...form.value, T_approver: uuid })
+        res = await Overtime_Edit({ ...form.value, T_approver: uuid, T_duration: time })
       }
       if (res.Code === 200) {
         ElMessage.success(`${isNew ? '申请' : '修改'}成功!`)
@@ -136,7 +129,6 @@ const callbackDrawer = (done: Fn) => {
 }
 const resetForm = (formEl: FormInstance | undefined) => {
   if (!formEl) return
-  fileList.value = []
   formEl.resetFields()
 }
 const validate_float = (rule: any, value: any, callback: any) => {
@@ -191,59 +183,6 @@ const onResize = () => {
   const height = document.documentElement.clientHeight
   return height / 2
 }
-
-// upload file
-interface FileListType {
-  url: string
-  name: string
-}
-let prove_img = true
-const upload = ref()
-const fileList = ref<FileListType[]>([])
-const dialogImageUrl = ref('')
-const dialogVisible = ref(false)
-let uploadData = { token: '', key: '' }
-
-// 图片查看 放大
-const handlePictureCardPreview = async (file: any) => {
-  dialogImageUrl.value = file.url as string
-  dialogVisible.value = true
-}
-// 图片上传之前
-const beforeUpload = async (file: any) => {
-  let reg = /^image/g
-  if (!reg.test(file.type)) {
-    ElMessage.error('必须上传图片!!')
-    return
-  }
-  prove_img = false
-  let suffix = file.type.split('/')[1]
-  const res: any = await UpFileToken({ User_tokey: globalStore.GET_User_tokey, T_suffix: suffix })
-  uploadData.token = res.Data
-  uploadData.key = file.name
-}
-// 图片上传超出界限
-const handleExceed: UploadProps['onExceed'] = (files: any) => {
-  upload.value.clearFiles()
-  const file = files[0] as UploadRawFile
-  file.uid = genFileId()
-  upload.value.handleStart(file)
-  upload.value.submit()
-}
-// 图片上传成功
-const onSuccess = (response: any) => {
-  form.value.T_prove_img = response.key
-  prove_img = true
-  ElMessage.success('图片上传成功!!')
-}
-// 图片上传失败
-const onError = () => {
-  ElMessage.error('图片上传失败!!')
-}
-// 图片移除
-const handleRemove: UploadProps['onRemove'] = () => {
-  form.value.T_prove_img = ''
-}
 </script>
 
 <template>
@@ -353,27 +292,9 @@ const handleRemove: UploadProps['onRemove'] = () => {
           <el-input v-model.number="form.T_duration" autocomplete="off" placeholder="请假时长" />
         </el-form-item>
         <el-form-item label="取证:" :label-width="formLabelWidth">
-          <el-upload
-            ref="upload"
-            :disabled="disabled"
-            v-model:file-list="fileList"
-            action="https://up-z2.qiniup.com"
-            list-type="picture-card"
-            :limit="1"
-            :auto-upload="true"
-            :before-upload="beforeUpload"
-            :on-success="onSuccess"
-            :on-error="onError"
-            :on-exceed="handleExceed"
-            :on-remove="handleRemove"
-            :on-preview="handlePictureCardPreview"
-            :data="uploadData"
-          >
+          <Upload ref="uploadRef" :isImg="true" :limit="1" v-model="form.T_prove_img" accept="image/*">
             <el-icon><Plus /></el-icon>
-          </el-upload>
-          <el-dialog v-model="dialogVisible">
-            <img w-full :src="dialogImageUrl" class="full-img" alt="Preview Image" />
-          </el-dialog>
+          </Upload>
         </el-form-item>
         <el-form-item label="内容:" :label-width="formLabelWidth" prop="T_text">
           <el-input

+ 67 - 61
src/views/workAttendance/Overtime.vue

@@ -40,7 +40,7 @@ const initParam = {
   User_tokey: globalStore.GET_User_tokey
 }
 const getSalaryParams = (row: any) => {
-  userInfo.value = { ...row, T_prove_img: import.meta.env.VITE_BZD_ERPOSS_APP_API + row.T_prove_img }
+  userInfo.value = { ...row }
 }
 
 const LeaveUser = async (T_State: number) => {
@@ -97,67 +97,73 @@ onUnmounted(() => {
         </template>
       </TableBase>
     </div>
-    <el-row class="h-100 f-1 margin-left-3">
-      <el-col :span="24" class="h-100" style="overflow: hidden">
-        <el-card class="m-b-3 b-show-0">
-          <h3 class="title-user m-b-5">员工基本信息</h3>
-          <div class="info-content">
-            <el-avatar shape="square" size="large" :icon="UserFilled" />
-            <div class="info-name">
-              <h4 class="m-b-3">名字:{{ userInfo.T_user_name }}</h4>
+    <transition
+      leave-active-class="animate__animated animate__bounceOutRight"
+      enter-active-class="animate__animated animate__bounceInDown"
+    >
+      <el-row class="h-100 f-1 margin-left-3" v-if="userInfo.Id">
+        <el-col :span="24" class="h-100" style="overflow: hidden">
+          <el-card class="m-b-3 b-show-0">
+            <h3 class="title-user m-b-5">员工基本信息</h3>
+            <div class="info-content">
+              <el-avatar shape="square" size="large" :icon="UserFilled" />
+              <div class="info-name">
+                <h4 class="m-b-3">名字:{{ userInfo.T_user_name }}</h4>
+              </div>
             </div>
-          </div>
-        </el-card>
-        <el-card class="m-b-3 b-show-0" :style="{ height: cardHeight + 'px' }">
-          <el-row>
-            <el-col :span="12"
-              ><div>
-                开始时间:<el-tag v-if="userInfo.T_start_time" type="success" effect="dark">
-                  {{ userInfo.T_start_time }}
-                </el-tag>
-              </div></el-col
-            >
-            <el-col :span="12"
-              ><div>
-                结束时间:<el-tag v-if="userInfo.T_end_time" type="success" effect="dark">
-                  {{ userInfo.T_end_time }}
-                </el-tag>
-              </div></el-col
-            >
-          </el-row>
-          <el-row>
-            <el-col :span="12"
-              ><div>
-                加班时长:<el-tag v-if="userInfo.T_duration" type="success" effect="dark">
-                  {{ getFormatDuration(userInfo.T_duration as any) }}
-                </el-tag>
-              </div></el-col
-            >
-          </el-row>
-          <el-row>
-            <el-col style="display: flex">
-              取证:
-              <img :src="userInfo.T_prove_img" class="img" />
-            </el-col>
-          </el-row>
-          <el-row>
-            <el-col>
-              <span class="ml-3 w-35 text-gray-600 inline-flex items-center">内容:</span>
-              <el-input
-                v-model="userInfo.T_text"
-                :autosize="{ minRows: 4, maxRows: 6 }"
-                type="textarea"
-                placeholder="Please input"
-              />
-            </el-col>
-          </el-row>
-          <div class="btn">
-            <el-button type="primary" @click="LeaveUser(1)">通过</el-button>
-            <el-button type="danger" @click="LeaveUser(0)">不通过</el-button>
-          </div>
-        </el-card>
-      </el-col>
-    </el-row>
+          </el-card>
+          <el-card class="m-b-3 b-show-0" :style="{ height: cardHeight + 'px' }">
+            <el-row>
+              <el-col :span="12"
+                ><div>
+                  开始时间:<el-tag v-if="userInfo.T_start_time" type="success" effect="dark">
+                    {{ userInfo.T_start_time }}
+                  </el-tag>
+                </div></el-col
+              >
+              <el-col :span="12"
+                ><div>
+                  结束时间:<el-tag v-if="userInfo.T_end_time" type="success" effect="dark">
+                    {{ userInfo.T_end_time }}
+                  </el-tag>
+                </div></el-col
+              >
+            </el-row>
+            <el-row>
+              <el-col :span="12"
+                ><div>
+                  加班时长:<el-tag v-if="userInfo.T_duration" type="success" effect="dark">
+                    {{ getFormatDuration(userInfo.T_duration as any) }}
+                  </el-tag>
+                </div></el-col
+              >
+            </el-row>
+            <el-row>
+              <el-col style="display: flex">
+                取证:
+                <img v-if="userInfo.T_prove_img" :src="userInfo.T_prove_img" class="img" />
+                <span v-else>无</span>
+              </el-col>
+            </el-row>
+            <el-row>
+              <el-col>
+                <span class="ml-3 w-35 text-gray-600 inline-flex items-center">内容:</span>
+                <el-input
+                  v-model="userInfo.T_text"
+                  :autosize="{ minRows: 4, maxRows: 6 }"
+                  type="textarea"
+                  placeholder="加班内容"
+                />
+              </el-col>
+            </el-row>
+            <div class="btn">
+              <el-button type="primary" @click="LeaveUser(1)">通过</el-button>
+              <el-button type="danger" @click="LeaveUser(0)">不通过</el-button>
+            </div>
+          </el-card>
+        </el-col>
+      </el-row>
+    </transition>
   </div>
 </template>