浏览代码

个人账号-个人中心

YY 2 年之前
父节点
当前提交
38f0baef4b

+ 1 - 1
src/components/ValidCode.vue

@@ -43,7 +43,7 @@ const resetCode = () => {
   createCode();
 };
 </script>
-<style scoped lang="less">
+<style scoped lang="scss">
 .code {
   width: 100px;
   height: 40px;

+ 595 - 0
src/components/account/parts/user-project.vue

@@ -0,0 +1,595 @@
+<template>
+  <div id="user-project">
+    <el-row>
+      <el-col :span="24" class="main animate__animated animate__backInRight">
+        <component :is="CForm" :fields="fields" :form="form" :rules="rules" @save="toSave" @dataChange="dataChange" :span="24" labelWidth="140px">
+          <!-- 基本 -->
+          <template #gender>
+            <el-option v-for="i in genderList" :key="i.model" :label="i.dict_label" :value="i.dict_value"></el-option>
+          </template>
+          <template #education>
+            <el-option v-for="i in educationList" :key="i.model" :label="i.dict_label" :value="i.dict_value"></el-option>
+          </template>
+          <template #degree>
+            <el-option v-for="i in degreeList" :key="i.model" :label="i.dict_label" :value="i.dict_value"></el-option>
+          </template>
+          <!-- 工作室 -->
+          <template #card="{ item }">
+            <component
+              style="width: 100%"
+              :is="CUpload"
+              :model="item.model"
+              :limit="2"
+              url="/files/studioadmin/register/upload"
+              :list="form[item.model]"
+              listType="picture"
+              @change="onUpload"
+            ></component>
+          </template>
+          <template #team_phone>
+            <el-col :span="12">
+              <el-form-item label="内容" label-width="100px" prop="team_phone.phone">
+                <el-input v-model="form.team_phone.phone" placeholder="请输入联系电话"></el-input>
+              </el-form-item>
+            </el-col>
+            <el-col :span="12">
+              <el-form-item label="是否公开" label-width="80px">
+                <el-select v-model="form.team_phone.is_show" placeholder="请选择" style="width: 100%">
+                  <el-option v-for="i in isshowList" :key="i.model" :label="i.dict_label" :value="i.dict_value"></el-option>
+                </el-select>
+              </el-form-item>
+            </el-col>
+          </template>
+          <template #zc>
+            <el-option v-for="i in zcList" :key="i.model" :label="i.dict_label" :value="i.dict_value"></el-option>
+          </template>
+          <template #zc_file="{ item }">
+            <component
+              style="width: 100%"
+              :is="CUpload"
+              :model="item.model"
+              :limit="1"
+              url="/files/studioadmin/register/upload"
+              :list="form[item.model]"
+              listType="picture"
+              @change="onUpload"
+            ></component>
+          </template>
+          <template #fields>
+            <el-option v-for="i in fieldList" :key="i.dict_value" :label="i.dict_label" :value="i.dict_value"></el-option>
+          </template>
+          <template #direction>
+            <el-button type="primary" size="mini" @click="addDriection()">添加</el-button>
+            <el-col :span="24">
+              <el-table :data="form.direction" border size="mini">
+                <el-table-column type="index" label="序号" width="50" align="center"> </el-table-column>
+                <el-table-column prop="name" label="名称" align="center">
+                  <template v-slot="scope">
+                    <el-input v-model="scope.row.name" placeholder="请输入技术需求方向名称,名称长度不可超过八个字" maxlength="8"></el-input>
+                  </template>
+                </el-table-column>
+                <el-table-column label="操作" align="center" width="100">
+                  <template v-slot="scope">
+                    <el-button size="mini" type="danger" @click="delDriection(scope.row)">删除</el-button>
+                  </template>
+                </el-table-column>
+              </el-table>
+            </el-col>
+          </template>
+          <template #case>
+            <el-button type="primary" size="mini" @click="addCase()">添加</el-button>
+            <el-col :span="24">
+              <el-table :data="form.case" border size="mini">
+                <el-table-column type="index" label="序号" width="50" align="center"> </el-table-column>
+                <el-table-column prop="name" label="名称" align="center">
+                  <template v-slot="scope">
+                    <el-input
+                      v-model="scope.row.name"
+                      placeholder="请输入服务企业代表性案例"
+                      type="textarea"
+                      maxlength="100"
+                      show-word-limit
+                      :autosize="{ minRows: 3, maxRows: 5 }"
+                    ></el-input>
+                  </template>
+                </el-table-column>
+                <el-table-column label="操作" align="center" width="100">
+                  <template v-slot="scope">
+                    <el-button size="mini" type="danger" @click="delCase(scope.row)">删除</el-button>
+                  </template>
+                </el-table-column>
+              </el-table>
+            </el-col>
+          </template>
+          <template #case_file="{ item }">
+            <component
+              style="width: 100%"
+              :is="CUpload"
+              :model="item.model"
+              :limit="5"
+              url="/files/studioadmin/basic/upload"
+              :list="form[item.model]"
+              listType="picture"
+              @change="onUpload"
+            ></component>
+          </template>
+          <template #is_job>
+            <el-option v-for="i in isjobList" :key="i.model" :label="i.dict_label" :value="i.dict_value"></el-option>
+          </template>
+        </component>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+<script setup lang="ts">
+import moment from 'moment';
+import store from '@/stores/counter';
+import CForm from '@common/src/components/frame/c-form.vue';
+import CUpload from '@common/src/components/frame/c-upload.vue';
+import type { FormRules } from 'element-plus';
+import type { Ref } from 'vue';
+import { ref, reactive, watch, toRefs } from 'vue';
+import { ElMessage } from 'element-plus';
+import { isIdentityId, isIdentityPhone } from '@common/src/util/checkCard';
+import { UserStudioApplyStore } from '@common/src/stores/studio/role/userStudioApply';
+import { BasicStore } from '@common/src/stores/project/basic';
+import { UsersStore } from '@common/src/stores/users/users';
+import { UnitStore } from '@common/src/stores/users/unit';
+import { DictDataStore } from '@common/src/stores/users/sysdictdata'; // 字典表
+import type { IQueryResult } from '@/util/types.util';
+const userStudioApply = UserStudioApplyStore();
+const unit = UnitStore();
+const basic = BasicStore();
+const users = UsersStore();
+const sysdictdata = DictDataStore();
+const props = defineProps({
+  userInfo: { type: Object, default: () => {} },
+});
+const { userInfo } = toRefs(props);
+
+let fields: Ref<any[]> = ref([]);
+const checkCard = (rule: any, value: any, callback: any) => {
+  if (!value) {
+    return callback(new Error('请输入身份证号'));
+  } else {
+    var errorMsg = isIdentityId(value);
+    if (errorMsg != '') {
+      callback(new Error(errorMsg));
+    } else {
+      callback();
+    }
+  }
+};
+const checkPhone = (rule: any, value: any, callback: any) => {
+  if (!value) {
+    return callback(new Error('请输入手机号'));
+  } else {
+    var errorMsg = isIdentityPhone(value);
+    if (errorMsg != '') {
+      callback(new Error(errorMsg));
+    } else {
+      callback();
+    }
+  }
+};
+const rules = reactive<FormRules>({
+  name: [{ required: true, message: '请输入姓名', trigger: 'blur' }],
+  // card_type: [{ required: true, message: '请选择证件类别', trigger: 'change' }],
+  num: [{ required: true, validator: checkCard, trigger: 'change' }],
+  gender: [{ required: true, message: '请选择性别', trigger: 'change' }],
+  birth: [{ required: true, message: '请选择出生年月', trigger: 'change' }],
+  phone: [{ required: true, validator: checkPhone, trigger: 'blur', type: '手机号' }],
+  email: [{ required: true, message: '请输入电子邮箱', trigger: 'blur' }],
+  education: [{ required: true, message: '请选择学历', trigger: 'change' }],
+  degree: [{ required: true, message: '请选择学位', trigger: 'change' }],
+  unit_name: [{ required: true, message: '请输入工作单位', trigger: 'blur' }],
+  work_phone: [{ required: true, message: '请输入办公电话', trigger: 'blur' }],
+  title: [{ required: true, message: '请输入职称', trigger: 'blur' }],
+  // 工作室
+  live_place: [{ required: true, message: '请输入居住地', trigger: 'blur' }],
+  card: [{ required: true, message: '请上传身份证', trigger: 'change' }],
+  team_name: [{ required: false, message: '请输入团队联系人', trigger: 'blur' }],
+  'team_phone.phone': [{ required: true, validator: checkPhone, trigger: 'blur', type: '团队联系人电话' }],
+  zc: [{ required: true, message: '请选择专业技术职称', trigger: 'change' }],
+  zc_file: [{ required: true, message: '请上传职称证明', trigger: 'change' }],
+  part_job: [{ required: false, message: '请输入社会兼职', trigger: 'blur' }],
+  fields: [{ required: true, message: '请选择研究领域', trigger: 'change' }],
+  direction: [{ required: true, message: '请添加研究方向', trigger: 'change' }],
+  case: [{ required: false, message: '请上传服务企业代表性案例', trigger: 'change' }],
+  case_file: [{ required: false, message: '请上传案例证明材料', trigger: 'change' }],
+  is_job: [{ required: true, message: '请选择是否为在职人员', trigger: 'change' }],
+});
+const form: Ref<{
+  phone: { phone: string; is_show: boolean };
+  email: { is_show: boolean; email: string };
+  card: any;
+  team_phone: { phone: string; is_show: boolean };
+  zc_file: any;
+  fields: any;
+  direction: any;
+  case: any;
+  case_file: any;
+  settle_file: any;
+  job_zc_file: any;
+  name: string;
+  team_name: string;
+  birth: any;
+  address: string;
+  num: string;
+  gender: string;
+}> = ref({
+  phone: { phone: '', is_show: false },
+  email: { is_show: false, email: '' },
+  card: [],
+  team_phone: { phone: '', is_show: false },
+  zc_file: [],
+  fields: [],
+  direction: [],
+  case: [],
+  case_file: [],
+  settle_file: [],
+  job_zc_file: [],
+  name: '',
+  team_name: '',
+  birth: '',
+  address: '',
+  num: '',
+  gender: '',
+});
+
+// 字典表
+// 依托单位名称
+let unit_name: Ref<string> = ref('');
+// 证件类别
+let cardtypeList: Ref<any> = ref([]);
+// 性别
+let genderList: Ref<any> = ref([]);
+// 学历
+let educationList: Ref<any> = ref([]);
+// 学位
+let degreeList: Ref<any> = ref([]);
+// 领域
+let fieldList: Ref<any> = ref([]);
+// 专业技术职称
+let zcList: Ref<any> = ref([]);
+// 是否为在职人员
+let isjobList: Ref<any> = ref([]);
+// 是否公开
+let isshowList: Ref<any> = ref([]);
+
+let user = store.state.user as { _id: string; role_type: string; account: string; unit: String; unit_address: string };
+
+// 查询
+const search = async (e: any) => {
+  let field1: any = [];
+  let field = [
+    { label: '姓名', model: 'name', options: { disabled: true } },
+    // { label: '证件类别', model: 'card_type', type: 'select' },
+    { label: '身份证号', model: 'num', options: { disabled: true } },
+    { label: '性别', model: 'gender', type: 'select', options: { disabled: true } },
+    { label: '出生年月', model: 'birth', type: 'date', options: { disabled: true } },
+    { label: '手机号', model: 'phone', options: { disabled: true } },
+    { label: '电子邮箱', model: 'email', options: { disabled: true } },
+    { label: '学历', model: 'education', type: 'select' },
+    { label: '学位', model: 'degree', type: 'select' },
+    { label: '工作单位', model: 'unit_name', options: { disabled: true } },
+    { label: '办公电话', model: 'work_phone' },
+    { label: '职称', model: 'title' },
+    // { label: '研究领域(2)', model: 'fields', type: 'selectMany', options: { placeholder: '请选择(多选,不超过2个)' } },
+  ];
+  if (e && e.is_studio == 'Y') {
+    let fields_studio = [
+      { label: '居住地', model: 'live_place' },
+      { label: '身份证(正反)', model: 'card', custom: true },
+      { label: '团队联系人', model: 'team_name' },
+      { label: '团队联系人手机号', model: 'team_phone', custom: true },
+      { label: '专业技术职称', model: 'zc', type: 'select' },
+      { label: '职称证明', model: 'zc_file', custom: true },
+      { label: '社会兼职', model: 'part_job' },
+      { label: '研究领域(2)', model: 'fields', type: 'selectMany', options: { placeholder: '请选择(多选,不超过2个)' } },
+      { label: '研究方向', model: 'direction', custom: true },
+      { label: '服务企业代表性案例', model: 'case', custom: true },
+      { label: '案例证明材料', model: 'case_file', custom: true },
+      { label: '是否为在职人员', model: 'is_job', type: 'select' },
+    ];
+    field1 = [...field, ...fields_studio];
+  }
+  fields.value = field1;
+  let p1s: any;
+  let p1: any = {
+    name: e.nick_name,
+    card_type: '0',
+    num: e.card,
+    gender: getcard(e.card, 'gender') || '',
+    birth: getcard(e.card, 'birth') || '',
+    phone: e.phone,
+    email: e.email,
+    education: '',
+    degree: '',
+    unit: e.unit,
+    unit_name: unit_name.value,
+    work_phone: '',
+    title: '',
+  };
+  if (e && e.is_studio == 'Y') {
+    let form_studio = {
+      live_place: '',
+      card: [],
+      team_name: e.nick_name || '',
+      team_phone: { phone: e.phone || '' },
+      zc: '',
+      zc_file: [],
+      part_job: '',
+      fields: [],
+      direction: [],
+      case: [],
+      case_file: [],
+      is_job: '',
+    };
+    p1s = { ...p1, ...form_studio };
+  }
+  // 有数据:
+  let res: IQueryResult = await basic.self();
+  if (res.errcode == '0') {
+    p1s = res.data as {};
+    p1s.unit_name = unit_name.value;
+    if (e.is_studio == 'Y') {
+      let is_stu: IQueryResult = await userStudioApply.query({ user_id: user._id });
+      if (is_stu.errcode == 0) {
+        if (is_stu.total > 0) {
+          let is_stu_info = is_stu.data[0];
+          delete is_stu_info._id;
+          delete is_stu_info.id;
+          p1s = { ...p1s, ...is_stu_info };
+        } else {
+          let form_studio = {
+            live_place: '',
+            card: [],
+            team_name: e.nick_name || '',
+            team_phone: { phone: e.phone ? e.phone : '' },
+            zc: '',
+            zc_file: [],
+            part_job: '',
+            fields: [],
+            direction: [],
+            case: [],
+            case_file: [],
+            is_job: '',
+          };
+          p1s = { ...p1s, ...form_studio };
+        }
+      }
+    }
+  } else {
+    console.log('暂无基础数据');
+    if (e.is_studio == 'Y') {
+      let is_stu: IQueryResult = await userStudioApply.query({ user_id: user._id });
+      if (is_stu.errcode == 0) {
+        if (is_stu.total > 0) {
+          let is_stu_info = is_stu.data[0];
+          delete is_stu_info._id;
+          delete is_stu_info.id;
+          p1s = { ...p1s, ...is_stu_info };
+        } else {
+          let form_studio = {
+            live_place: '',
+            card: [],
+            team_name: e.nick_name || '',
+            team_phone: { phone: e.phone ? e.phone : '' },
+            zc: '',
+            zc_file: [],
+            part_job: '',
+            fields: [],
+            direction: [],
+            case: [],
+            case_file: [],
+            is_job: '',
+          };
+          p1s = { ...p1s, ...form_studio };
+        }
+      }
+    }
+  }
+  form.value = p1s;
+};
+
+// 查找出生年月,性别
+const getcard = (value: any, model: string) => {
+  if (value) {
+    if (model == 'brith') {
+      let birthday = '';
+      if (value != null && value != '') {
+        if (value.length == 15) birthday = '19' + value.slice(6, 12);
+        else if (value.length == 18) birthday = value.slice(6, 14);
+        birthday = birthday.replace(/(.{4})(.{2})/, '$1-$2-');
+        if (birthday) return birthday;
+        else return null;
+      }
+    } else if (model == 'gender') {
+      // 获取性别
+      let gender = '';
+      if (parseInt(value.substr(16, 1)) % 2 == 1) gender = '0';
+      else if (parseInt(value.substr(16, 1)) % 2 == 0) gender = '1';
+      else gender = '2';
+      if (gender) return gender;
+      else return null;
+    }
+  }
+};
+// 技术需求方向添加
+const addDriection = () => {
+  let direction = form.value.direction;
+  if (direction.length >= 5) ElMessage({ type: 'error', message: '研究方向最多添加五个' });
+  else direction.push({ id: moment().valueOf(), name: '' });
+  form.value.direction = direction;
+};
+// 研究方向删除
+const delDriection = (e: { id: string }) => {
+  let direction = form.value.direction.filter((i: any) => i.id != e.id);
+  form.value.direction = direction;
+};
+// 案例添加
+const addCase = () => {
+  let cases = form.value.case;
+  if (cases.length >= 5) ElMessage({ type: 'error', message: '案例最多添加五个' });
+  else cases.push({ id: moment().valueOf(), name: '' });
+  form.value.case = cases;
+};
+// 案例删除
+const delCase = (e: { id: string }) => {
+  let cases = form.value.case.filter((i: any) => i.id != e.id);
+  form.value.case = cases;
+};
+// 数据选择
+const dataChange = (model: string, value: any) => {
+  if (model == 'fields') {
+    if (value.length > 2) ElMessage({ type: 'error', message: '数据过多,请重新选择' });
+  }
+};
+const onUpload = (e: { model: string; value: Array<[]> }) => {
+  const { model, value } = e;
+  form.value[model] = value;
+};
+const emit = defineEmits(['updateBasic']);
+// 审核保存
+const toSave = async (data: any) => {
+  console.log(data);
+  let res: IQueryResult;
+  let is_stu: IQueryResult;
+  if (userInfo.value.is_studio == 'Y') {
+    is_stu = await userStudioApply.query({ user_id: user._id });
+    if (is_stu.total === 0) createApply(data);
+    else {
+      let id = is_stu.data[0]._id;
+      console.log('已有科学家工作室信息,不可重复入驻');
+      let form = {
+        user_id: user._id,
+        name: data.name,
+        brith: data.birth,
+        phone: { phone: data.phone || '' },
+        email: { email: data.email || '' },
+        education: data.education,
+        degree: data.degree,
+        live_place: data.live_place,
+        card: data.card,
+        team_name: data.team_name || '',
+        team_phone: data.team_phone,
+        company: unit_name.value,
+        address: user.unit_address,
+        zc: data.zc,
+        zc_file: data.zc_file,
+        part_job: data.part_job || '',
+        fields: data.fields,
+        direction: data.direction,
+        case: data.case,
+        case_file: data.case_file || [],
+        is_job: data.is_job,
+        _id: id,
+      };
+      let arr: IQueryResult = await userStudioApply.update(form);
+      console.log(arr);
+    }
+  }
+  if (data._id) {
+    res = await basic.update(data);
+  } else {
+    res = await basic.create(data);
+    let refresh: IQueryResult = await users.refresh();
+    if (refresh.errcode == 0) {
+      let p1: any = refresh.data as [];
+      if (refresh.data) localStorage.setItem('token', p1);
+    }
+  }
+  if (res.errcode == 0) {
+    ElMessage({ type: 'success', message: '维护信息成功' });
+    search(userInfo.value);
+  }
+};
+// 创建入驻信息
+const createApply = async (e: any) => {
+  let form = {
+    user_id: user._id,
+    name: e.name,
+    brith: e.birth,
+    phone: { phone: e.phone || '' },
+    email: { email: e.email || '' },
+    education: e.education,
+    degree: e.degree,
+    live_place: e.live_place,
+    card: e.card,
+    team_name: e.team_name || '',
+    team_phone: e.team_phone,
+    company: unit_name.value,
+    address: user.unit_address,
+    zc: e.zc,
+    zc_file: e.zc_file,
+    part_job: e.part_job || '',
+    fields: e.fields,
+    direction: e.direction,
+    case: e.case,
+    case_file: e.case_file || [],
+    is_job: e.is_job,
+  };
+  let res: IQueryResult = await userStudioApply.create(form);
+  if (res.errcode == 0) emit('updateBasic');
+};
+const searchOther = async () => {
+  // 是否公开
+  const p1: IQueryResult = await sysdictdata.query({ dict_type: 's_is_show' });
+  if (p1.errcode == 0) isshowList.value = p1.data as [];
+  // 领域
+  const p2: IQueryResult = await sysdictdata.query({ dict_type: 'studio_field' });
+  if (p2.errcode == 0) fieldList.value = p2.data as [];
+  // 是否为在职人员
+  const p3: IQueryResult = await sysdictdata.query({ dict_type: 'studio_scientist_is_job' });
+  if (p3.errcode == 0) isjobList.value = p3.data as [];
+  // 专业技术职称
+  const p4: IQueryResult = await sysdictdata.query({ dict_type: 's-builddesire-zc' });
+  if (p4.errcode == 0) {
+    let arr1 = p4.data as [];
+    let data = arr1.filter((i: any) => i.dict_value != '0');
+    zcList.value = data;
+  }
+  // 性别
+  const p5: IQueryResult = await sysdictdata.query({ dict_type: 'sys_user_sex' });
+  if (p5.errcode == 0) genderList.value = p5.data as [];
+  // 学历
+  const p6: IQueryResult = await sysdictdata.query({ dict_type: 'education' });
+  if (p6.errcode == 0) educationList.value = p6.data as [];
+  // 学位
+  const p7: IQueryResult = await sysdictdata.query({ dict_type: 'degree' });
+  if (p7.errcode == 0) degreeList.value = p7.data as [];
+  // 依托单位信息
+  const p8: IQueryResult = await unit.fetch(user.unit);
+  if (p8.errcode == 0) {
+    let arr2 = p8.data as { unit_name: string };
+    if (arr2 && arr2.unit_name) unit_name.value = arr2.unit_name;
+  }
+  // 证件类别
+  const p9: IQueryResult = await sysdictdata.query({ dict_type: 'basic_card_type' });
+  if (p9.errcode == 0) cardtypeList.value = p9.data as [];
+};
+watch(userInfo, async (val) => {
+  if (val && val._id) {
+    await searchOther();
+    await search(val);
+  }
+  if (val && val.nick_name) form.value.name = val.nick_name;
+  if (val && val.card) {
+    form.value.num = val.card;
+    let gender = getcard(val.card, 'gender') || '';
+    let birth = getcard(val.card, 'birth') || '';
+    form.value.gender = gender;
+    form.value.birth = birth;
+  }
+  if (val && val.phone) form.value.phone = val.phone;
+
+  if (val && val.email) form.value.email = val.email;
+  if (val && val.is_studio == 'Y') {
+    if (val && val.nick_name) form.value.team_name = val.nick_name;
+    if (val && val.phone) form.value.team_phone.phone = val.phone;
+  }
+});
+</script>
+
+<style lang="scss" scoped></style>

+ 457 - 0
src/components/account/parts/user-studio.vue

@@ -0,0 +1,457 @@
+<template>
+  <div id="user-studio">
+    <el-row>
+      <el-col :span="24" class="main">
+        <el-col :span="24" class="onn">
+          <c-search :is_title="false">
+            <template v-slot:isslot>
+              <el-button type="primary" size="small">{{ status }}</el-button>
+            </template>
+          </c-search>
+        </el-col>
+        <el-col :span="24" class="two">
+          <component :is="CForm" :fields="fields" :form="form" :rules="rules" @save="toSave" @dataChange="dataChange" :span="24" labelWidth="130px">
+            <template #phone>
+              <el-col :span="12">
+                <el-form-item label="内容" label-width="100px" prop="phone.phone">
+                  <el-input v-model="form.phone.phone" placeholder="请输入手机号" disabled></el-input>
+                </el-form-item>
+              </el-col>
+              <el-col :span="12">
+                <el-form-item label="是否公开" label-width="80px">
+                  <el-select v-model="form.phone.is_show" placeholder="请选择" style="width: 100%">
+                    <el-option v-for="i in isshowList" :key="i.model" :label="i.dict_label" :value="i.dict_value"></el-option>
+                  </el-select>
+                </el-form-item>
+              </el-col>
+            </template>
+            <template #email>
+              <el-col :span="12">
+                <el-form-item label="内容" label-width="100px" prop="email.email">
+                  <el-input v-model="form.email.email" placeholder="请输入电子邮箱"></el-input>
+                </el-form-item>
+              </el-col>
+              <el-col :span="12">
+                <el-form-item label="是否公开" label-width="80px">
+                  <el-select v-model="form.email.is_show" placeholder="请选择" style="width: 100%">
+                    <el-option v-for="i in isshowList" :key="i.model" :label="i.dict_label" :value="i.dict_value"></el-option>
+                  </el-select>
+                </el-form-item>
+              </el-col>
+            </template>
+            <template #education>
+              <el-option v-for="i in educationList" :key="i.model" :label="i.dict_label" :value="i.dict_value"></el-option>
+            </template>
+            <template #degree>
+              <el-option v-for="i in degreeList" :key="i.model" :label="i.dict_label" :value="i.dict_value"></el-option>
+            </template>
+            <template #card="{ item }">
+              <component
+                style="width: 100%"
+                :is="CUpload"
+                :model="item.model"
+                :limit="2"
+                url="/files/studioadmin/register/upload"
+                :list="form[item.model]"
+                listType="picture"
+                @change="onUpload"
+              ></component>
+            </template>
+            <template #team_phone>
+              <el-col :span="12">
+                <el-form-item label="内容" label-width="100px" prop="team_phone.phone">
+                  <el-input v-model="form.team_phone.phone" placeholder="请输入联系电话"></el-input>
+                </el-form-item>
+              </el-col>
+              <el-col :span="12">
+                <el-form-item label="是否公开" label-width="80px">
+                  <el-select v-model="form.team_phone.is_show" placeholder="请选择" style="width: 100%">
+                    <el-option v-for="i in isshowList" :key="i.model" :label="i.dict_label" :value="i.dict_value"></el-option>
+                  </el-select>
+                </el-form-item>
+              </el-col>
+            </template>
+            <template #zc>
+              <el-option v-for="i in zcList" :key="i.model" :label="i.dict_label" :value="i.dict_value"></el-option>
+            </template>
+            <template #zc_file="{ item }">
+              <component
+                style="width: 100%"
+                :is="CUpload"
+                :model="item.model"
+                :limit="1"
+                url="/files/studioadmin/register/upload"
+                :list="form[item.model]"
+                listType="picture"
+                @change="onUpload"
+              ></component>
+            </template>
+            <template #fields>
+              <el-option v-for="i in fieldList" :key="i.dict_value" :label="i.dict_label" :value="i.dict_value"></el-option>
+            </template>
+            <template #direction>
+              <el-button type="primary" size="small" @click="addDriection()">添加</el-button>
+              <el-col :span="24">
+                <el-table :data="form.direction" border size="small">
+                  <el-table-column type="index" label="序号" width="50" align="center"> </el-table-column>
+                  <el-table-column prop="name" label="名称" align="center">
+                    <template v-slot="scope">
+                      <el-input v-model="scope.row.name" placeholder="请输入技术需求方向名称,名称长度不可超过八个字" maxlength="8"></el-input>
+                    </template>
+                  </el-table-column>
+                  <el-table-column label="操作" align="center" width="100">
+                    <template v-slot="scope">
+                      <el-button size="small" type="danger" @click="delDriection(scope.row)">删除</el-button>
+                    </template>
+                  </el-table-column>
+                </el-table>
+              </el-col>
+            </template>
+            <template #case>
+              <el-button type="primary" size="small" @click="addCase()">添加</el-button>
+              <el-col :span="24">
+                <el-table :data="form.case" border size="small">
+                  <el-table-column type="index" label="序号" width="50" align="center"> </el-table-column>
+                  <el-table-column prop="name" label="名称" align="center">
+                    <template v-slot="scope">
+                      <el-input
+                        v-model="scope.row.name"
+                        placeholder="请输入服务企业代表性案例"
+                        type="textarea"
+                        maxlength="100"
+                        show-word-limit
+                        :autosize="{ minRows: 3, maxRows: 5 }"
+                      ></el-input>
+                    </template>
+                  </el-table-column>
+                  <el-table-column label="操作" align="center" width="100">
+                    <template v-slot="scope">
+                      <el-button size="small" type="danger" @click="delCase(scope.row)">删除</el-button>
+                    </template>
+                  </el-table-column>
+                </el-table>
+              </el-col>
+            </template>
+            <template #case_file="{ item }">
+              <component
+                style="width: 100%"
+                :is="CUpload"
+                :model="item.model"
+                :limit="5"
+                url="/files/studioadmin/basic/upload"
+                :list="form[item.model]"
+                listType="picture"
+                @change="onUpload"
+              ></component>
+            </template>
+            <template #is_job>
+              <el-option v-for="i in isjobList" :key="i.model" :label="i.dict_label" :value="i.dict_value"></el-option>
+            </template>
+          </component>
+        </el-col>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+<script setup lang="ts">
+import moment from 'moment';
+import store from '@/stores/counter';
+import CForm from '@common/src/components/frame/c-form.vue';
+import CUpload from '@common/src/components/frame/c-upload.vue';
+import type { FormRules } from 'element-plus';
+import type { Ref } from 'vue';
+import { ref, reactive, watch, toRefs } from 'vue';
+import { ElMessage } from 'element-plus';
+import { isIdentityId, isIdentityPhone } from '@common/src/util/checkCard';
+import { UserStudioApplyStore } from '@common/src/stores/studio/role/userStudioApply';
+import { UnitStore } from '@common/src/stores/users/unit';
+import { DictDataStore } from '@common/src/stores/users/sysdictdata'; // 字典表
+import type { IQueryResult } from '@/util/types.util';
+const userStudioApply = UserStudioApplyStore();
+const unit = UnitStore();
+const sysdictdata = DictDataStore();
+const props = defineProps({
+  userInfo: { type: Object, default: () => {} },
+});
+const { userInfo } = toRefs(props);
+
+let fields: Ref<any[]> = ref([
+  { label: '姓名', model: 'name', options: { disabled: true } },
+  { label: '出生年月', model: 'brith', type: 'date', options: { disabled: true } },
+  { label: '手机号', model: 'phone', custom: true, options: { disabled: true } },
+  { label: '电子邮箱', model: 'email', custom: true, options: { disabled: true } },
+  { label: '学历', model: 'education', type: 'select' },
+  { label: '学位', model: 'degree', type: 'select' },
+  { label: '居住地', model: 'live_place' },
+  { label: '身份证(正反)', model: 'card', custom: true },
+  { label: '团队联系人', model: 'team_name' },
+  { label: '团队联系人手机号', model: 'team_phone', custom: true },
+  { label: '所在单位全称', model: 'company', options: { disabled: true } },
+  { label: '所在单位地址', model: 'address', options: { disabled: true } },
+  { label: '专业技术职称', model: 'zc', type: 'select' },
+  { label: '职称证明', model: 'zc_file', custom: true },
+  { label: '社会兼职', model: 'part_job' },
+  { label: '研究领域(2)', model: 'fields', type: 'selectMany', options: { placeholder: '请选择(多选,不超过2个)' } },
+  { label: '研究方向', model: 'direction', custom: true },
+  { label: '服务企业代表性案例', model: 'case', custom: true },
+  { label: '案例证明材料', model: 'case_file', custom: true },
+  { label: '是否为在职人员', model: 'is_job', type: 'select' },
+]);
+const checkPhone = (rule: any, value: any, callback: any) => {
+  if (!value) {
+    return callback(new Error(`请输入${rule.type}`));
+  } else {
+    var errorMsg = isIdentityPhone(value);
+    if (errorMsg != '') {
+      callback(new Error(errorMsg));
+    } else {
+      callback();
+    }
+  }
+};
+const rules = reactive<FormRules>({
+  name: [{ required: true, message: '请输入姓名', trigger: 'blur' }],
+  brith: [{ required: true, message: '请选择出生年月', trigger: 'change' }],
+  live_place: [{ required: true, message: '请输入居住地', trigger: 'blur' }],
+  'phone.phone': [{ required: true, validator: checkPhone, trigger: 'blur', type: '手机号' }],
+  'email.email': [{ required: true, message: '请输入电子邮箱', trigger: 'blur' }],
+  education: [{ required: true, message: '请选择学历', trigger: 'change' }],
+  degree: [{ required: true, message: '请选择学位', trigger: 'change' }],
+  card: [{ required: true, message: '请上传身份证', trigger: 'change' }],
+  team_name: [{ required: false, message: '请输入团队联系人', trigger: 'blur' }],
+  'team_phone.phone': [{ required: true, validator: checkPhone, trigger: 'blur', type: '团队联系人电话' }],
+  company: [{ required: true, message: '请输入所在单位全称', trigger: 'blur' }],
+  address: [{ required: true, message: '请输入所在单位地址', trigger: 'blur' }],
+  zc: [{ required: true, message: '请选择专业技术职称', trigger: 'change' }],
+  zc_file: [{ required: true, message: '请上传职称证明', trigger: 'change' }],
+  part_job: [{ required: false, message: '请输入社会兼职', trigger: 'blur' }],
+  fields: [{ required: true, message: '请选择研究领域', trigger: 'change' }],
+  direction: [{ required: true, message: '请添加研究方向', trigger: 'change' }],
+  case: [{ required: false, message: '请上传服务企业代表性案例', trigger: 'change' }],
+  case_file: [{ required: false, message: '请上传案例证明材料', trigger: 'change' }],
+  is_job: [{ required: true, message: '请选择是否为在职人员', trigger: 'change' }],
+});
+const form: Ref<{
+  phone: { phone: string; is_show: boolean };
+  email: { is_show: boolean; email: string };
+  card: any;
+  team_phone: { phone: string; is_show: boolean };
+  zc_file: any;
+  fields: any;
+  direction: any;
+  case: any;
+  case_file: any;
+  settle_file: any;
+  job_zc_file: any;
+  name: string;
+  team_name: string;
+  brith: any;
+  address: string;
+}> = ref({
+  phone: { phone: '', is_show: false },
+  email: { is_show: false, email: '' },
+  card: [],
+  team_phone: { phone: '', is_show: false },
+  zc_file: [],
+  fields: [],
+  direction: [],
+  case: [],
+  case_file: [],
+  settle_file: [],
+  job_zc_file: [],
+  name: '',
+  team_name: '',
+  brith: '',
+  address: '',
+});
+
+// 字典表
+// 审核状态
+let statusList: Ref<any> = ref([]);
+// 依托单位名称
+let unit_name: Ref<string> = ref('');
+let status: Ref<string> = ref('暂无');
+// 学历
+let educationList: Ref<any> = ref([]);
+// 学位
+let degreeList: Ref<any> = ref([]);
+// 领域
+let fieldList: Ref<any> = ref([]);
+// 专业技术职称
+let zcList: Ref<any> = ref([]);
+// 是否为在职人员
+let isjobList: Ref<any> = ref([]);
+// 是否公开
+let isshowList: Ref<any> = ref([]);
+
+let user = store.state.user as { _id: string; role_type: string; account: string; unit: String };
+
+// 查询
+const search = async (e: any) => {
+  let p1: any = {
+    user_id: e._id,
+    name: e.nick_name || '',
+    brith: getcard(e.card, 'brith') || '',
+    phone: { phone: e.phone || '' },
+    email: { email: e.email || '' },
+    education: '',
+    degree: '',
+    live_place: '',
+    card: [],
+    team_name: e.nick_name || '',
+    team_phone: { phone: e.phone || '' },
+    company: unit_name.value || e.unit,
+    address: e.unit_address || '',
+    zc: '',
+    zc_file: [],
+    part_job: '',
+    fields: [],
+    direction: [],
+    case: [],
+    case_file: [],
+    is_job: '',
+  };
+  // // 查询已申请数据状态
+  let res: IQueryResult = await userStudioApply.query({ user_id: user._id });
+  if (res.errcode == '0') {
+    if (res.total > 0) {
+      let data = res.data[0] as { status: string };
+      p1 = data;
+    }
+  }
+  if (p1 && p1.status) searchStatus(p1.status);
+  form.value = p1;
+};
+
+const searchStatus = (e: string) => {
+  let info = '待审中';
+  let data = statusList.value.find((i: any) => i.dict_value == e);
+  if (data) info = data.dict_label;
+  status.value = info;
+};
+// 查找出生年月,性别
+const getcard = (value: any, model: string) => {
+  if (value) {
+    if (model == 'brith') {
+      let birthday = '';
+      if (value != null && value != '') {
+        if (value.length == 15) birthday = '19' + value.slice(6, 12);
+        else if (value.length == 18) birthday = value.slice(6, 14);
+        birthday = birthday.replace(/(.{4})(.{2})/, '$1-$2-');
+        if (birthday) return birthday;
+        else return null;
+      }
+    } else if (model == 'gender') {
+      // 获取性别
+      let gender = '';
+      if (parseInt(value.substr(16, 1)) % 2 == 1) gender = '0';
+      else if (parseInt(value.substr(16, 1)) % 2 == 0) gender = '1';
+      else gender = '2';
+      if (gender) return gender;
+      else return null;
+    }
+  }
+};
+// 技术需求方向添加
+const addDriection = () => {
+  let direction = form.value.direction;
+  if (direction.length >= 5) ElMessage({ type: 'error', message: '研究方向最多添加五个' });
+  else direction.push({ id: moment().valueOf(), name: '' });
+  form.value.direction = direction;
+};
+// 研究方向删除
+const delDriection = (e: { id: string }) => {
+  let direction = form.value.direction.filter((i: any) => i.id != e.id);
+  form.value.direction = direction;
+};
+// 案例添加
+const addCase = () => {
+  let cases = form.value.case;
+  if (cases.length >= 5) ElMessage({ type: 'error', message: '案例最多添加五个' });
+  else cases.push({ id: moment().valueOf(), name: '' });
+  form.value.case = cases;
+};
+// 案例删除
+const delCase = (e: { id: string }) => {
+  let cases = form.value.case.filter((i: any) => i.id != e.id);
+  form.value.case = cases;
+};
+// 数据选择
+const dataChange = (model: string, value: any) => {
+  if (model == 'fields') {
+    if (value.length > 2) ElMessage({ type: 'error', message: '数据过多,请重新选择' });
+  }
+};
+const onUpload = (e: { model: string; value: Array<[]> }) => {
+  const { model, value } = e;
+  form.value[model] = value;
+};
+const emit = defineEmits(['updateBasic']);
+// 审核保存
+const toSave = async (data: { status: string; _id: string }) => {
+  let res: IQueryResult;
+  if (data.status == '2') data.status = '0';
+  if (data._id) res = await userStudioApply.update(data);
+  else res = await userStudioApply.create(data);
+  if (res.errcode == 0) {
+    ElMessage({ type: 'success', message: '维护信息成功' });
+    search(userInfo.value);
+  }
+  emit('updateBasic');
+};
+const searchOther = async () => {
+  // 是否公开
+  const p1: IQueryResult = await sysdictdata.query({ dict_type: 's_is_show' });
+  if (p1.errcode == 0) isshowList.value = p1.data as [];
+  // 领域
+  const p2: IQueryResult = await sysdictdata.query({ dict_type: 'studio_field' });
+  if (p2.errcode == 0) fieldList.value = p2.data as [];
+  // 是否为在职人员
+  const p3: IQueryResult = await sysdictdata.query({ dict_type: 'studio_scientist_is_job' });
+  if (p3.errcode == 0) isjobList.value = p3.data as [];
+  // 专业技术职称
+  const p4: IQueryResult = await sysdictdata.query({ dict_type: 's-builddesire-zc' });
+  if (p4.errcode == 0) {
+    let arr1 = p4.data as [];
+    let data = arr1.filter((i: any) => i.dict_value != '0');
+    zcList.value = data;
+  }
+  // 审核状态
+  const p5: IQueryResult = await sysdictdata.query({ dict_type: 'studio_status' });
+  if (p5.errcode == 0) statusList.value = p5.data as [];
+  // 学历
+  const p6: IQueryResult = await sysdictdata.query({ dict_type: 'education' });
+  if (p6.errcode == 0) educationList.value = p6.data as [];
+  // 学位
+  const p7: IQueryResult = await sysdictdata.query({ dict_type: 'degree' });
+  if (p7.errcode == 0) degreeList.value = p7.data as [];
+  // 依托单位信息
+  const p8: IQueryResult = await unit.fetch(user.unit);
+  if (p8.errcode == 0) {
+    let arr2 = p8.data as { unit_name: string };
+    if (arr2 && arr2.unit_name) unit_name.value = arr2.unit_name;
+  }
+};
+watch(userInfo, async (val) => {
+  if (val && val._id) {
+    await searchOther();
+    await search(val);
+  }
+  if (val && val.nick_name) {
+    form.value.name = val.nick_name;
+    form.value.team_name = val.nick_name;
+  }
+  if (val && val.card) {
+    let brith = getcard(val.card, 'brith');
+    form.value.brith = brith;
+  }
+  if (val && val.phone) {
+    form.value.phone.phone = val.phone;
+    form.value.team_phone.phone = val.phone;
+  }
+  if (val && val.email) form.value.email.email = val.email;
+  if (val && val.unit_address) form.value.address = val.unit_address;
+});
+</script>
+
+<style lang="scss" scoped></style>

+ 233 - 0
src/components/account/user-1.vue

@@ -0,0 +1,233 @@
+<template>
+  <div id="user-1">
+    <el-row>
+      <el-col :span="24" class="main animate__animated animate__backInRight">
+        <el-col :span="24" class="one">
+          <el-col :span="24" class="title">一、账号信息</el-col>
+          <el-col :span="24" class="info">
+            <component :is="CForm" :span="12" :fields="fields" :form="form" :rules="rules" labelWidth="160px" @save="toSave">
+              <template #unit>
+                <el-select
+                  v-model="form.unit"
+                  filterable
+                  remote
+                  clearable
+                  placeholder="请输入单位完整名称,以便于查询"
+                  :remote-method="querySearch"
+                  @change="handleSelect"
+                  :loading="loading"
+                  style="width: 100%"
+                  :disabled="unit_disabled"
+                >
+                  <el-option v-for="item in unitList" :key="item._id" :label="item.unit_name" :value="item._id"> </el-option>
+                </el-select>
+              </template>
+              <template #is_studio>
+                <el-option v-for="i in isnoList" :key="i.model" :label="i.dict_label" :value="i.dict_value"></el-option>
+              </template>
+            </component>
+          </el-col>
+        </el-col>
+        <el-col :span="24" class="two">
+          <el-col :span="24" class="title">二、基础信息</el-col>
+          <el-col :span="24" class="info">
+            <component :is="UserProject" v-if="env == 'project'" :userInfo="form" @updateBasic="updateBasic"></component>
+            <component :is="UserStudio" v-else-if="env == 'studio'" :userInfo="form" @updateBasic="updateBasic"></component>
+          </el-col>
+        </el-col>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+<script setup lang="ts">
+import store from '@/stores/counter';
+import CForm from '@common/src/components/frame/c-form.vue';
+import UserProject from '@common/src/components/account/parts/user-project.vue';
+import UserStudio from '@common/src/components/account/parts/user-studio.vue';
+import type { FormRules } from 'element-plus';
+import type { Ref } from 'vue';
+import { ref, reactive, onMounted } from 'vue';
+import { UserStudioApplyStore } from '@common/src/stores/studio/role/userStudioApply';
+import { UsersStore } from '@common/src/stores/users/users';
+import { UnitStore } from '@common/src/stores/users/unit';
+import { DictDataStore } from '@common/src/stores/users/sysdictdata'; // 字典表
+import type { IQueryResult } from '@/util/types.util';
+const userStudioApply = UserStudioApplyStore();
+const unit = UnitStore();
+const users = UsersStore();
+const sysdictdata = DictDataStore();
+// 项目设置标签
+let env: Ref<string> = ref('');
+
+let fields: Ref<any[]> = ref([]);
+const rules = reactive<FormRules>({
+  account: [{ required: true, message: '登录账号', trigger: 'blur' }],
+  nick_name: [{ required: true, message: '姓名', trigger: 'blur' }],
+  // card: [{ required: true, validator: checkCard, trigger: 'blur' }],
+  // phone: [{ required: true, validator: checkPhone, trigger: 'blur' }],
+  email: [{ required: true, message: '邮箱', trigger: 'blur' }],
+  unit: [{ required: true, message: '单位全称', trigger: 'change' }],
+  unit_address: [{ required: true, message: '单位地址', trigger: 'blur' }],
+});
+const form: Ref<{
+  is_super: boolean;
+  role: any;
+  unit: string;
+  unit_address: string;
+}> = ref({ is_super: false, role: [], unit: '', unit_address: '' });
+// 依托单位
+let unitList: Ref<any> = ref([]);
+// 字典表
+// 是否
+let isnoList: Ref<any> = ref([]);
+// 是否可更改
+let unit_disabled: Ref<boolean> = ref(false);
+let loading: Ref<boolean> = ref(false);
+let unit_status: Ref<string> = ref('1');
+let user = store.state.user as { _id: string; role_type: string; account: string };
+
+onMounted(async () => {
+  await searchOther();
+  env.value = import.meta.env.VITE_OUT_DIR;
+  await search();
+});
+// 查询
+const search = async () => {
+  const res: IQueryResult = await users.fetch(user._id);
+  if (res.errcode == 0) {
+    let p1 = res.data as { unit: string; is_super: boolean; role: any; unit_address: string };
+    let field = [
+      { label: '登录账号', model: 'account', options: { readonly: true } },
+      { label: '姓名', model: 'nick_name' },
+      { label: '身份证号', model: 'card' },
+      { label: '手机号', model: 'phone' },
+      { label: '电子邮箱', model: 'email' },
+      { label: '单位全称', model: 'unit', custom: true },
+      { label: '单位地址', model: 'unit_address' },
+      { label: '是否入驻科学家工作室', model: 'is_studio', type: 'select' },
+    ];
+    let unitInfo = await unit.fetch(p1.unit);
+    if (unitInfo.errcode == '0') {
+      let p2 = unitInfo.data as { _id: string };
+      unitList.value = [p2];
+      if (p2 && p2._id) {
+        unit_disabled.value = true;
+      } else {
+        console.log('无');
+      }
+    }
+    fields.value = field;
+    form.value = p1;
+  }
+};
+
+// 远程查询
+const querySearch = async (value: string) => {
+  loading.value = true;
+  let res = await unit.query({ unit_name: value });
+  if (res.errcode == 0) {
+    let list = [];
+    if (res.total > 0) {
+      list = res.data as [];
+      unit_status.value = '1';
+    } else {
+      list = [{ _id: value, unit_name: value }];
+      unit_status.value = '2';
+    }
+    unitList.value = list;
+  }
+  loading.value = false;
+};
+// 选择-查询地址
+const handleSelect = async (value: string) => {
+  if (unit_status.value == '1') {
+    let data = unitList.value.find((i: any) => i._id == value);
+    if (data) form.value.unit_address = data.unit_address;
+    else form.value.unit_address = '';
+  } else {
+    form.value.unit_address = '';
+  }
+};
+// 已有科学家工作室信息,已入驻
+const updateBasic = async () => {
+  let res = await users.update({ _id: user._id, is_studio: 'Y', account: user.account });
+  if (res.errcode == 0) {
+    search();
+  }
+};
+
+// 审核保存
+const toSave = async (data: { nick_name: string; card: string; phone: string; email: string; unit_address: string }) => {
+  let res: IQueryResult = await users.update(data);
+  if (res.errcode == 0) {
+    search();
+    // 判断是否有basic信息和工作室信息
+    if (env.value == 'project') {
+      //
+    } else if (env.value == 'studio') {
+      let arr: IQueryResult = await userStudioApply.query({ user_id: user._id });
+      if (arr.errcode == 0) {
+        if (arr.total > 0) {
+          console.log('已有入驻信息,信息同步');
+          let info = arr.data[0];
+          info.name = data.nick_name;
+          info.team_name = data.nick_name;
+          info.brith = getcard(data.card, 'brith');
+          info.phone.phone = data.phone;
+          info.team_phone.phone = data.phone;
+          info.email.email = data.email;
+          info.address = data.unit_address;
+          let aee: IQueryResult = await userStudioApply.update(info);
+          console.log(aee);
+        }
+      }
+    }
+  }
+};
+// 查找出生年月,性别
+const getcard = (value: any, model: string) => {
+  if (value) {
+    if (model == 'brith') {
+      let birthday = '';
+      if (value != null && value != '') {
+        if (value.length == 15) {
+          birthday = '19' + value.slice(6, 12);
+        } else if (value.length == 18) {
+          birthday = value.slice(6, 14);
+        }
+        birthday = birthday.replace(/(.{4})(.{2})/, '$1-$2-');
+        if (birthday) return birthday;
+        else return null;
+      }
+    } else if (model == 'gender') {
+      // 获取性别
+      let gender = '';
+      if (parseInt(value.substr(16, 1)) % 2 == 1) {
+        gender = '0';
+      } else if (parseInt(value.substr(16, 1)) % 2 == 0) {
+        gender = '1';
+      } else {
+        gender = '2';
+      }
+      if (gender) return gender;
+      else return null;
+    }
+  }
+};
+const searchOther = async () => {
+  const p1: IQueryResult = await sysdictdata.query({ dict_type: 'sys_yes_no' });
+  isnoList.value = p1.data as [];
+};
+</script>
+
+<style lang="scss" scoped>
+.title {
+  font-size: 18px;
+  margin: 0 0 10px 0;
+}
+.main {
+  .one {
+    margin: 0 0 10px 0;
+  }
+}
+</style>

+ 67 - 0
src/stores/project/basic.ts

@@ -0,0 +1,67 @@
+import { ref, computed } from 'vue';
+import { defineStore } from 'pinia';
+import { AxiosWrapper } from '@/util/axios-wrapper';
+import _ from 'lodash';
+
+import type { IQueryType, IQueryResult, IQueryParams } from '@/util/types.util';
+const axios = new AxiosWrapper();
+const api = {
+  url: `/freeLabel/project/v1/api/basic`,
+};
+export const BasicStore = defineStore('basic', () => {
+  const count = ref(0);
+  const doubleCount = computed(() => count.value * 2);
+  function increment() {
+    count.value++;
+  }
+  const query = async ({ skip = 0, limit = undefined, ...info }: IQueryParams = {}): Promise<IQueryResult> => {
+    let cond: IQueryType = {};
+    if (skip) cond.skip = skip;
+    if (limit) cond.limit = limit;
+    cond = { ...cond, ...info };
+    const res = await axios.$get(`${api.url}`, cond);
+    return res;
+  };
+  const fetch = async (payload: any): Promise<IQueryResult> => {
+    const res = await axios.$get(`${api.url}/${payload}`);
+    return res;
+  };
+  const create = async (payload: any): Promise<IQueryResult> => {
+    const res = await axios.$post(`${api.url}`, payload);
+    return res;
+  };
+  const update = async (payload: any): Promise<IQueryResult> => {
+    const id = _.get(payload, 'id', _.get(payload, '_id'));
+    const res = await axios.$post(`${api.url}/${id}`, payload);
+    return res;
+  };
+  const del = async (payload: any): Promise<IQueryResult> => {
+    const res = await axios.$delete(`${api.url}/${payload}`);
+    return res;
+  };
+  const self = async (): Promise<IQueryResult> => {
+    const res = await axios.$delete(`${api.url}/self`);
+
+    return res;
+  };
+  const getPercent = async ({ skip = 0, limit = undefined, ...info }: IQueryParams = {}): Promise<IQueryResult> => {
+    let cond: IQueryType = {};
+    if (skip) cond.skip = skip;
+    if (limit) cond.limit = limit;
+    cond = { ...cond, ...info };
+    const res = await axios.$get(`${api.url}/percent`, cond);
+    return res;
+  };
+  return {
+    count,
+    doubleCount,
+    increment,
+    query,
+    fetch,
+    create,
+    update,
+    del,
+    self,
+    getPercent,
+  };
+});

+ 77 - 0
src/util/checkCard.ts

@@ -0,0 +1,77 @@
+export function isIdentityId(identityId: any) {
+  const patrn = /(^\d{15}$)|(^\d{17}(\d|X|x)$)/; //长度或格式校验
+  //地区校验
+  const aCity = {
+    11: '北京',
+    12: '天津',
+    13: '河北',
+    14: '山西',
+    15: '内蒙古',
+    21: '辽宁',
+    22: '吉林',
+    23: '黑龙江',
+    31: '上海',
+    32: '江苏',
+    33: '浙江',
+    34: '安徽',
+    35: '福建',
+    36: '江西',
+    37: '山东',
+    41: '河南',
+    42: '湖北',
+    43: '湖南',
+    44: '广东',
+    45: '广西',
+    46: '海南',
+    50: '重庆',
+    51: '四川',
+    52: '贵州',
+    53: '云南',
+    54: '西藏',
+    61: '陕西',
+    62: '甘肃',
+    63: '青海',
+    64: '宁夏',
+    65: '新疆',
+    71: '台湾',
+    81: '香港',
+    82: '澳门',
+    91: '国外',
+  };
+  // 出生日期验证
+  const sBirthday = (identityId.substr(6, 4) + '-' + Number(identityId.substr(10, 2)) + '-' + Number(identityId.substr(12, 2))).replace(/-/g, '/'),
+    d = new Date(sBirthday);
+  // 身份证号码校验 最后4位  包括最后一位的数字/字母X
+  let sum = 0;
+  const weights = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2],
+    codes = '10X98765432';
+  for (let i = 0; i < identityId.length - 1; i++) {
+    sum += identityId[i] * weights[i];
+  }
+  const last = codes[sum % 11]; //计算出来的最后一位身份证号码
+
+  let errorMsg = '';
+  if (identityId === '') {
+    errorMsg = '身份证号不能为空';
+  } else if (!patrn.exec(identityId)) {
+    errorMsg = '你输入的身份证长度或格式错误';
+  } else if (!aCity[parseInt(identityId.substr(0, 2))]) {
+    errorMsg = '你的身份证地区非法';
+  } else if (sBirthday != d.getFullYear() + '/' + (d.getMonth() + 1) + '/' + d.getDate()) {
+    errorMsg = '身份证上的出生日期非法';
+  }
+  // else if (identityId[identityId.length - 1] != last) {
+  //   errorMsg = '你输入的身份证号非法';
+  // }
+  return errorMsg;
+}
+export function isIdentityPhone(phone: any) {
+  const reg = /^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/;
+  let errorMsg = '';
+  if (phone === '') {
+    errorMsg = '手机号/联系电话不能为空';
+  } else if (reg.test(phone) == false) {
+    errorMsg = '手机号/联系电话格式不正确,请重新输入';
+  }
+  return errorMsg;
+}