guhongwei 3 tahun lalu
induk
melakukan
372cd0d274
41 mengubah file dengan 4158 tambahan dan 1 penghapusan
  1. 99 0
      src/router/index.js
  2. 1 1
      src/views/patent/admin/adminBtn.vue
  3. 175 0
      src/views/patent/admin/examine/analysis.vue
  4. 69 0
      src/views/patent/admin/examine/analysis/checkForm.vue
  5. 80 0
      src/views/patent/admin/examine/analysis/info-1.vue
  6. 109 0
      src/views/patent/admin/examine/analysis/list-1.vue
  7. 85 0
      src/views/patent/admin/examine/hairmess.vue
  8. 97 0
      src/views/patent/admin/examine/hairmess/list-1.vue
  9. 134 0
      src/views/patent/admin/examine/hairmess_autoCreate.vue
  10. 126 0
      src/views/patent/admin/examine/hairmess_create.vue
  11. 120 0
      src/views/patent/admin/examine/patent.vue
  12. 69 0
      src/views/patent/admin/examine/patent/checkForm.vue
  13. 96 0
      src/views/patent/admin/examine/patent/info-1.vue
  14. 124 0
      src/views/patent/admin/examine/patent/list-1.vue
  15. 72 0
      src/views/patent/admin/message/examine.vue
  16. 67 0
      src/views/patent/admin/message/notice.vue
  17. 79 0
      src/views/patent/admin/message/notice_create.vue
  18. 60 0
      src/views/patent/admin/message/parts/form-1.vue
  19. 99 0
      src/views/patent/admin/message/parts/list-1.vue
  20. 92 0
      src/views/patent/admin/message/parts/list-2.vue
  21. 95 0
      src/views/patent/admin/message/parts/list-3.vue
  22. 83 0
      src/views/patent/admin/message/parts/list-4.vue
  23. 68 0
      src/views/patent/admin/message/service.vue
  24. 287 0
      src/views/patent/admin/message/service_detail.vue
  25. 64 0
      src/views/patent/admin/message/warning.vue
  26. 157 0
      src/views/patent/admin/patent/assessment.vue
  27. 99 0
      src/views/patent/admin/patent/assessment/examine-1.vue
  28. 81 0
      src/views/patent/admin/patent/assessment/info-1.vue
  29. 115 0
      src/views/patent/admin/patent/assessment/list-1.vue
  30. 100 0
      src/views/patent/admin/patent/assessment_examine.vue
  31. 120 0
      src/views/patent/admin/patent/info.vue
  32. 262 0
      src/views/patent/admin/patent/info/detail-1.vue
  33. 98 0
      src/views/patent/admin/patent/info/list-1.vue
  34. 108 0
      src/views/patent/admin/patent/info/result-1.vue
  35. 84 0
      src/views/patent/admin/patent/info_create.vue
  36. 126 0
      src/views/patent/admin/patent/info_import.vue
  37. 67 0
      src/views/patent/admin/patent/info_result.vue
  38. 67 0
      src/views/patent/admin/patent/trans.vue
  39. 76 0
      src/views/patent/admin/patent/trans/info-1.vue
  40. 85 0
      src/views/patent/admin/patent/trans/list-1.vue
  41. 63 0
      src/views/patent/admin/patent/trans_info.vue

+ 99 - 0
src/router/index.js

@@ -325,6 +325,105 @@ const patent = [
     meta: { title: '专利交易-详细信息' },
     component: () => import('../views/patent/mech/transaction/info.vue'),
   },
+  // 管理用户
+  // 我的消息
+  {
+    path: '/patent/admin/message/service',
+    meta: { title: '咨询服务' },
+    component: () => import('../views/patent/admin/message/service.vue'),
+  },
+  {
+    path: '/patent/admin/message/service_detail',
+    meta: { title: '咨询服务-聊天详情' },
+    component: () => import('../views/patent/admin/message/service_detail.vue'),
+  },
+  {
+    path: '/patent/admin/message/notice',
+    meta: { title: '通知信息' },
+    component: () => import('../views/patent/admin/message/notice.vue'),
+  },
+  {
+    path: '/patent/admin/message/notice_create',
+    meta: { title: '通知信息-编辑通知' },
+    component: () => import('../views/patent/admin/message/notice_create.vue'),
+  },
+  {
+    path: '/patent/admin/message/examine',
+    meta: { title: '审核通知' },
+    component: () => import('../views/patent/admin/message/examine.vue'),
+  },
+  {
+    path: '/patent/admin/message/warning',
+    meta: { title: '专利预警' },
+    component: () => import('../views/patent/admin/message/warning.vue'),
+  },
+  // 专利审核
+  {
+    path: '/patent/admin/examine/patent',
+    meta: { title: '专利申请' },
+    component: () => import('../views/patent/admin/examine/patent.vue'),
+  },
+  {
+    path: '/patent/admin/examine/hairmess',
+    meta: { title: '分发消息' },
+    component: () => import('../views/patent/admin/examine/hairmess.vue'),
+  },
+  {
+    path: '/patent/admin/examine/hairmess_create',
+    meta: { title: '分发消息-添加消息' },
+    component: () => import('../views/patent/admin/examine/hairmess_create.vue'),
+  },
+  {
+    path: '/patent/admin/examine/hairmess_autoCreate',
+    meta: { title: '分发消息-自动分发消息' },
+    component: () => import('../views/patent/admin/examine/hairmess_autoCreate.vue'),
+  },
+  {
+    path: '/patent/admin/examine/analysis',
+    meta: { title: '查新检索' },
+    component: () => import('../views/patent/admin/examine/analysis.vue'),
+  },
+  // 专利管理
+  {
+    path: '/patent/admin/patent/info',
+    meta: { title: '专利信息' },
+    component: () => import('../views/patent/admin/patent/info.vue'),
+  },
+  {
+    path: '/patent/admin/patent/info_create',
+    meta: { title: '专利信息-添加专利' },
+    component: () => import('../views/patent/admin/patent/info_create.vue'),
+  },
+  {
+    path: '/patent/admin/patent/info_import',
+    meta: { title: '专利信息-导入专利' },
+    component: () => import('../views/patent/admin/patent/info_import.vue'),
+  },
+  {
+    path: '/patent/admin/patent/info_result',
+    meta: { title: '专利信息-导出结果' },
+    component: () => import('../views/patent/admin/patent/info_result.vue'),
+  },
+  {
+    path: '/patent/admin/patent/assessment',
+    meta: { title: '价值评估' },
+    component: () => import('../views/patent/admin/patent/assessment.vue'),
+  },
+  {
+    path: '/patent/admin/patent/assessment_examine',
+    meta: { title: '价值评估-审核信息' },
+    component: () => import('../views/patent/admin/patent/assessment_examine.vue'),
+  },
+  {
+    path: '/patent/admin/patent/trans',
+    meta: { title: '专利交易' },
+    component: () => import('../views/patent/admin/patent/trans.vue'),
+  },
+  {
+    path: '/patent/admin/patent/trans_info',
+    meta: { title: '专利交易-详细信息' },
+    component: () => import('../views/patent/admin/patent/trans_info.vue'),
+  },
 ];
 const web = [
   {

+ 1 - 1
src/views/patent/admin/adminBtn.vue

@@ -44,7 +44,7 @@ export default {
   created() {},
   methods: {
     pathBtn(type, path) {
-      this.$router.push({ path: `/service/patent/${type}/${path}` });
+      this.$router.push({ path: `/patent/${type}/${path}` });
     },
   },
   computed: {

+ 175 - 0
src/views/patent/admin/examine/analysis.vue

@@ -0,0 +1,175 @@
+<template>
+  <div id="analysis">
+    <admin-frame @search="search" :limit="limit" :total="total" topType="2" @back="back" :rightArrow="false" :useNav="false">
+      <template v-slot:info>
+        <list-1 :list="list" @view="view" @examine="toExamine" @toFile="toFile"></list-1>
+      </template>
+    </admin-frame>
+    <van-dialog class="dialog" v-model="show" title="详细信息" :show-confirm-button="false" show-cancel-button>
+      <info-1 :info="info"></info-1>
+    </van-dialog>
+    <van-dialog class="twoDialog" v-model="twoShow" title="审核信息" :show-confirm-button="false" :show-cancel-button="false" :closeOnClickOverlay="true">
+      <check-form :form="form" @onSubmit="onSubmit"></check-form>
+    </van-dialog>
+    <van-dialog class="thrDialog" v-model="thrShow" title="报告文件" :show-confirm-button="false" :show-cancel-button="false" :closeOnClickOverlay="true">
+      <van-form>
+        <van-field name="file" label="文件">
+          <template #input>
+            <van-uploader
+              :fileList="fileForm.file"
+              :max-count="1"
+              :after-read="(file) => toUpload(file, 'file')"
+              @delete="(file) => toDelete(file, 'file')"
+              accept="file"
+            />
+          </template>
+        </van-field>
+        <div class="btn">
+          <van-button type="danger" size="small" @click="thrClose">取消发送</van-button>
+          <van-button type="info" size="small" @click="thrSend">提交发送</van-button>
+        </div>
+      </van-form>
+    </van-dialog>
+  </div>
+</template>
+
+<script>
+import list1 from './analysis/list-1.vue';
+import info1 from './analysis/info-1.vue';
+import checkForm from './analysis/checkForm.vue';
+import adminFrame from '@frame/src/components/mobile-frame/mobile-main.vue';
+import { mapState, createNamespacedHelpers } from 'vuex';
+const { mapActions: patentanalysis } = createNamespacedHelpers('patentanalysis');
+const { mapActions: upload } = createNamespacedHelpers('upload');
+export default {
+  name: 'analysis',
+  props: {},
+  components: {
+    adminFrame,
+    list1,
+    info1,
+    checkForm,
+  },
+  data: function () {
+    return {
+      list: [],
+      limit: 5,
+      total: 0,
+      // 专利申请详细信息
+      show: false,
+      info: {},
+      // 专利申请审核信息
+      twoShow: false,
+      form: {},
+      // 报告文件
+      thrShow: false,
+      fileForm: {},
+    };
+  },
+  async created() {
+    await this.search();
+  },
+  methods: {
+    ...upload(['upload']),
+    ...patentanalysis(['query', 'check', 'update']),
+    async search({ skip = 0, limit = this.limit, ...info } = {}) {
+      info.admin_id = this.user._id;
+      let res = await this.query({ skip, limit, ...info });
+      if (this.$checkRes(res)) {
+        this.$set(this, `list`, res.data);
+        this.$set(this, `total`, res.total);
+      }
+    },
+    // 查看
+    view(data) {
+      if (!data.questions) data.questions = {};
+      this.$set(this, `info`, data);
+      this.show = true;
+    },
+    // 审核
+    toExamine(data) {
+      this.$set(this, `form`, data);
+      this.twoShow = true;
+    },
+    // 提交审核
+    async onSubmit(data) {
+      // 申请状态修改
+      const { id, remark, status } = this.form;
+      const obj = { id, status, remark };
+      const res = await this.check(obj);
+      if (this.$checkRes(res)) {
+        this.$toast({ type: `success`, message: `审核成功` });
+        this.twoShow = false;
+      } else {
+        this.$toast({ type: `fail`, message: `${res.errmsg}` });
+      }
+    },
+    // 发送文件
+    toFile(data) {
+      this.$set(this, `fileForm`, data);
+      this.thrShow = true;
+    },
+    // 提交发送
+    async thrSend() {
+      let data = this.fileForm;
+      data.status = '2';
+      let res = await this.update(data);
+      if (this.$checkRes(res)) {
+        this.$toast({ type: `success`, message: `发送文件成功` });
+        this.thrClose();
+      } else {
+        this.$toast({ type: `fail`, message: `${res.errmsg}` });
+      }
+    },
+    // 取消发送
+    thrClose() {
+      this.thrShow = false;
+    },
+    async toUpload({ file }, model) {
+      // 上传,赋值
+      const res = await this.upload({ file, dir: 'analysis' });
+      if (this.$checkRes(res)) {
+        this.$set(this.fileForm, model, [{ name: res.name, url: res.uri }]);
+      }
+    },
+    toDelete(file, model) {
+      const index = this.fileForm[model].findIndex((f) => _.isEqual(f, file));
+      this.fileForm[model].splice(index, 1);
+    },
+    // 返回
+    back() {
+      this.$router.push({ path: '/patent/index' });
+    },
+  },
+  computed: {
+    ...mapState(['user']),
+  },
+  metaInfo() {
+    return { title: this.$route.meta.title };
+  },
+  watch: {
+    test: {
+      deep: true,
+      immediate: true,
+      handler(val) {},
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped>
+.dialog {
+  /deep/.van-dialog__content {
+    height: 350px;
+    overflow-y: auto;
+  }
+}
+.thrDialog {
+  .btn {
+    text-align: center;
+    .van-button {
+      margin: 8px;
+    }
+  }
+}
+</style>

+ 69 - 0
src/views/patent/admin/examine/analysis/checkForm.vue

@@ -0,0 +1,69 @@
+<template>
+  <div id="checkForm">
+    <van-row>
+      <van-col span="24" class="main">
+        <van-form @submit="onSubmit">
+          <van-field v-model="form.name" name="name" label="发明名称" readonly />
+          <van-field name="status" label="审核状态">
+            <template #input>
+              <van-radio-group v-model="form.status" direction="horizontal">
+                <van-radio name="1">通过</van-radio>
+                <van-radio name="-1">拒绝</van-radio>
+              </van-radio-group>
+            </template>
+          </van-field>
+          <van-field
+            v-model="form.remark"
+            name="remark"
+            rows="8"
+            autosize
+            label="审核意见"
+            type="textarea"
+            maxlength="100"
+            placeholder="审核意见"
+            show-word-limit
+            :rules="[{ required: true, message: '审核意见' }]"
+          />
+          <div style="margin: 16px">
+            <van-button round block type="info" native-type="submit">提交</van-button>
+          </div>
+        </van-form>
+      </van-col>
+    </van-row>
+  </div>
+</template>
+
+<script>
+import { mapState, createNamespacedHelpers } from 'vuex';
+export default {
+  name: 'checkForm',
+  props: {
+    form: { type: Object },
+  },
+  components: {},
+  data: function () {
+    return {};
+  },
+  created() {},
+  methods: {
+    onSubmit(values) {
+      this.$emit('onSubmit', values);
+    },
+  },
+  computed: {
+    ...mapState(['user']),
+  },
+  metaInfo() {
+    return { title: this.$route.meta.title };
+  },
+  watch: {
+    test: {
+      deep: true,
+      immediate: true,
+      handler(val) {},
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped></style>

+ 80 - 0
src/views/patent/admin/examine/analysis/info-1.vue

@@ -0,0 +1,80 @@
+<template>
+  <div id="info-1">
+    <van-row>
+      <van-col span="24" class="main">
+        <van-form>
+          <van-field v-model="info.name" name="发明名称" label="发明名称" readonly />
+          <van-field v-model="info.apply_name" name="申请人" label="申请人" readonly />
+          <van-field v-model="info.type" name="专利类型" label="专利类型" readonly />
+          <van-field v-model="info.inventor" name="发明人" label="发明人" readonly />
+          <van-field v-model="info.contact" name="技术联系人" label="技术联系人" readonly />
+          <van-field v-model="info.phone" name="联系人电话" label="联系人电话" readonly />
+          <van-field v-model="info.email" name="联系人邮箱" label="联系人邮箱" readonly />
+          <van-field v-model="info.questions.q8" type="textarea" rows="1" autosize name="特殊情况说明" label="特殊情况说明" readonly />
+          <van-field v-model="info.questions.q1" type="textarea" rows="1" autosize name="本发明的技术领域" label="本发明的技术领域" readonly />
+          <van-field v-model="info.questions.q2" type="textarea" rows="1" autosize name="与本发明相关的背景技术" label="与本发明相关的背景技术" readonly />
+          <van-field
+            v-model="info.questions.q3"
+            type="textarea"
+            rows="1"
+            autosize
+            name="现有技术的缺点及本发明所要解决的技术问题"
+            label="现有技术的缺点及本发明所要解决的技术问题"
+            readonly
+          />
+          <van-field v-model="info.questions.q4" type="textarea" rows="1" autosize name="本发明技术方案的详细阐述" label="本发明技术方案的详细阐述" readonly />
+          <van-field v-model="info.questions.q5" type="textarea" rows="1" autosize name="本申请的关键点和欲保护点" label="本申请的关键点和欲保护点" readonly />
+          <van-field
+            v-model="info.questions.q6"
+            type="textarea"
+            rows="1"
+            autosize
+            name="与本发明最相似,相近的实现技术,方案相比,本发明有何优点"
+            label="与本发明最相似,相近的实现技术,方案相比,本发明有何优点"
+            readonly
+          />
+          <van-field
+            v-model="info.questions.q7"
+            type="textarea"
+            rows="1"
+            autosize
+            name="针对本发明技术方案,是否还有别的替代方案"
+            label="针对本发明技术方案,是否还有别的替代方案"
+            readonly
+          />
+        </van-form>
+      </van-col>
+    </van-row>
+  </div>
+</template>
+
+<script>
+import { mapState, createNamespacedHelpers } from 'vuex';
+export default {
+  name: 'info-1',
+  props: {
+    info: { type: Object },
+  },
+  components: {},
+  data: function () {
+    return {};
+  },
+  created() {},
+  methods: {},
+  computed: {
+    ...mapState(['user']),
+  },
+  metaInfo() {
+    return { title: this.$route.meta.title };
+  },
+  watch: {
+    test: {
+      deep: true,
+      immediate: true,
+      handler(val) {},
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped></style>

+ 109 - 0
src/views/patent/admin/examine/analysis/list-1.vue

@@ -0,0 +1,109 @@
+<template>
+  <div id="list-1">
+    <van-row>
+      <van-col span="24" class="main">
+        <van-col span="24" class="list" v-for="(item, index) in list" :key="index">
+          <van-col span="24" class="title textOver">
+            {{ item.name }}
+          </van-col>
+          <van-col span="24" class="other">
+            <van-col span="24" class="otherInfo">
+              申请人:<span>{{ item.apply_name || '暂无' }}</span>
+            </van-col>
+            <van-col span="24" class="otherInfo">
+              申请类型:<span>{{ item.type || '暂无' }}</span>
+            </van-col>
+            <van-col span="24" class="otherInfo">
+              申请状态:<span>{{ getStu(item.status) }}</span>
+            </van-col>
+          </van-col>
+          <van-col span="24" class="btn">
+            <van-button size="small" type="info" @click="view(item)">查看信息</van-button>
+            <van-button size="small" type="info" @click="examine(item)" v-if="item.status == '0'">审核申请</van-button>
+            <van-button size="small" type="info" @click="toFile(item)" v-if="item.status == '1' || item.status == '2'">报告文件</van-button>
+          </van-col>
+        </van-col>
+      </van-col>
+    </van-row>
+  </div>
+</template>
+
+<script>
+import { mapState, createNamespacedHelpers } from 'vuex';
+export default {
+  name: 'list-1',
+  props: {
+    list: { type: Array },
+  },
+  components: {},
+  data: function () {
+    return {};
+  },
+  created() {},
+  methods: {
+    view(data) {
+      this.$emit('view', data);
+    },
+    examine(data) {
+      this.$emit('examine', data);
+    },
+    toFile(data) {
+      this.$emit('toFile', data);
+    },
+    // 整理状态
+    getStu(status) {
+      if (status == '0') return '已提交给相应机构,请等待审核';
+      else if (status == '1') return '管理员审核通过,请及时发送相应文件!';
+      else if (status == '-1') return '管理员审核未通过,请查看审核意见,并重新提交申请';
+      else if (status == '2') return '文件已发送';
+    },
+  },
+  computed: {
+    ...mapState(['user']),
+  },
+  metaInfo() {
+    return { title: this.$route.meta.title };
+  },
+  watch: {
+    test: {
+      deep: true,
+      immediate: true,
+      handler(val) {},
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped>
+.main {
+  padding: 8px 8px 0 8px;
+  .list {
+    background-color: #fff;
+    margin: 0 0 8px 0;
+    padding: 8px;
+    border-radius: 5px;
+    .title {
+      font-size: 16px;
+      font-weight: bold;
+      margin: 0 0 5px 0;
+    }
+    .other {
+      margin: 0 0 5px 0;
+      .otherInfo {
+        font-size: 14px;
+        color: #666;
+        margin: 0 0 5px 0;
+        span {
+          color: #000;
+        }
+      }
+    }
+    .btn {
+      text-align: center;
+      .van-button {
+        margin: 0 5px;
+      }
+    }
+  }
+}
+</style>

+ 85 - 0
src/views/patent/admin/examine/hairmess.vue

@@ -0,0 +1,85 @@
+<template>
+  <div id="hairmess">
+    <admin-frame @search="search" :limit="limit" :total="total" topType="2" @back="back" :rightArrow="false" :useNav="false">
+      <template v-slot:info>
+        <van-col span="24" class="btn">
+          <!-- <van-button type="info" size="small" @click="add">手动分发</van-button> -->
+          <van-button type="info" size="small" @click="twoAdd">自动分发</van-button>
+        </van-col>
+        <van-col span="24">
+          <list-1 :list="list"></list-1>
+        </van-col>
+      </template>
+    </admin-frame>
+  </div>
+</template>
+
+<script>
+import list1 from './hairmess/list-1.vue';
+import adminFrame from '@frame/src/components/mobile-frame/mobile-main.vue';
+import { mapState, createNamespacedHelpers } from 'vuex';
+const { mapActions: patentwarning } = createNamespacedHelpers('patentwarning');
+export default {
+  name: 'hairmess',
+  props: {},
+  components: {
+    adminFrame,
+    list1,
+  },
+  data: function () {
+    return {
+      limit: 5,
+      total: 0,
+      list: [],
+    };
+  },
+  async created() {
+    this.search();
+  },
+  methods: {
+    ...patentwarning(['query']),
+    async search({ skip = 0, limit = this.limit, searchName, ...info } = {}) {
+      let res = await this.query({ skip, limit, ...info });
+      if (this.$checkRes(res)) {
+        this.$set(this, `list`, res.data);
+        this.$set(this, `total`, res.total);
+      }
+    },
+    // 分发消息创建
+    add() {
+      this.$router.push({ path: '/patent/admin/examine/hairmess_create' });
+    },
+    // 自动分发消息
+    twoAdd() {
+      this.$router.push({ path: '/patent/admin/examine/hairmess_autoCreate' });
+    },
+    // 返回
+    back() {
+      this.$router.push({ path: '/patent/index' });
+    },
+  },
+  computed: {
+    ...mapState(['user']),
+  },
+  metaInfo() {
+    return { title: this.$route.meta.title };
+  },
+  watch: {
+    test: {
+      deep: true,
+      immediate: true,
+      handler(val) {},
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped>
+.btn {
+  margin: 10px 0;
+  text-align: center;
+  .van-button {
+    margin: 0 10px;
+  }
+}
+</style>

+ 97 - 0
src/views/patent/admin/examine/hairmess/list-1.vue

@@ -0,0 +1,97 @@
+<template>
+  <div id="list-1">
+    <van-row>
+      <van-col span="24" class="main">
+        <van-col span="24" class="list" v-for="(item, index) in list" :key="index">
+          <van-col span="24" class="title textOver">
+            {{ item.create_number }}
+          </van-col>
+          <van-col span="24" class="other">
+            <van-col span="24" class="otherInfo">
+              专利名称:<span>{{ item.patent_name || '暂无' }}</span>
+            </van-col>
+            <van-col span="24" class="otherInfo">
+              接收人:<span>{{ item.to_name || '暂无' }}</span>
+            </van-col>
+          </van-col>
+          <van-col span="24" class="btn">
+            <van-button size="small" type="info" @click="download(item)">下载文件</van-button>
+          </van-col>
+        </van-col>
+      </van-col>
+    </van-row>
+  </div>
+</template>
+
+<script>
+import { mapState, createNamespacedHelpers } from 'vuex';
+export default {
+  name: 'list-1',
+  props: {
+    list: { type: Array },
+  },
+  components: {},
+  data: function () {
+    return {};
+  },
+  created() {},
+  methods: {
+    // 查看详情
+    download(data) {
+      if (data.file_url.length > 0) {
+        let url = data.file_url.map((i) => i.url);
+        window.location.href = `${process.env.VUE_APP_HOST}/${url[0]}`;
+      } else {
+        this.$toast({ type: `fail`, message: `未上传文件` });
+      }
+    },
+  },
+  computed: {
+    ...mapState(['user']),
+  },
+  metaInfo() {
+    return { title: this.$route.meta.title };
+  },
+  watch: {
+    test: {
+      deep: true,
+      immediate: true,
+      handler(val) {},
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped>
+.main {
+  padding: 8px 8px 0 8px;
+  .list {
+    background-color: #fff;
+    margin: 0 0 8px 0;
+    padding: 8px;
+    border-radius: 5px;
+    .title {
+      font-size: 16px;
+      font-weight: bold;
+      margin: 0 0 5px 0;
+    }
+    .other {
+      margin: 0 0 5px 0;
+      .otherInfo {
+        font-size: 14px;
+        color: #666;
+        margin: 0 0 5px 0;
+        span {
+          color: #000;
+        }
+      }
+    }
+    .btn {
+      text-align: center;
+      .van-button {
+        margin: 5px;
+      }
+    }
+  }
+}
+</style>

+ 134 - 0
src/views/patent/admin/examine/hairmess_autoCreate.vue

@@ -0,0 +1,134 @@
+<template>
+  <div id="hairmess">
+    <admin-frame topType="2" @back="back" :rightArrow="false" :usePage="false" :useNav="false">
+      <template v-slot:info>
+        <van-form label-width="4em">
+          <van-field name="uri" label="文件">
+            <template #input>
+              <van-uploader
+                :fileList="form.uri"
+                :max-count="1"
+                :after-read="(file) => toUpload(file, 'uri')"
+                @delete="(file) => toDelete(file, 'uri')"
+                accept="file"
+              />
+            </template>
+          </van-field>
+          <van-col span="24" class="btn">
+            <van-button type="danger" size="small" @click="back">取消发送</van-button>
+            <van-button type="info" size="small" @click="onSubmit">确认发送</van-button>
+          </van-col>
+        </van-form>
+        <van-col span="24" class="one">
+          <van-col span="24" class="list" v-for="(item, index) in list" :key="index">
+            <van-col span="24" class="title">{{ item.key }}</van-col>
+            <van-col span="24" class="other">
+              说明:<span>{{ item.word }}</span>
+            </van-col>
+          </van-col>
+        </van-col>
+      </template>
+    </admin-frame>
+  </div>
+</template>
+
+<script>
+import adminFrame from '@frame/src/components/mobile-frame/mobile-main.vue';
+import { mapState, createNamespacedHelpers } from 'vuex';
+const { mapActions: upload } = createNamespacedHelpers('upload');
+const { mapActions: patentwarning } = createNamespacedHelpers('patentwarning');
+
+export default {
+  name: 'hairmess',
+  props: {},
+  components: {
+    adminFrame,
+  },
+  data: function () {
+    return {
+      form: {},
+      uri: '',
+      list: '',
+    };
+  },
+  async created() {},
+  methods: {
+    ...upload(['upload']),
+    ...patentwarning(['import']),
+    // 提交
+    async onSubmit() {
+      let data = { uri: this.uri };
+      let res = await this.import(data);
+      if (this.$checkRes(res)) {
+        if (res.data) this.$set(this, `list`, res.data);
+        this.$toast({ type: `success`, message: `操作成功` });
+      } else {
+        this.$toast({ type: `success`, message: `${res.errmsg}` });
+      }
+    },
+    async toUpload({ file }, model) {
+      // 上传,赋值
+      const res = await this.upload({ file, dir: 'warning' });
+      if (this.$checkRes(res)) {
+        this.$set(this.form, model, [{ name: res.name, url: res.uri }]);
+        this.$set(this, `uri`, res.uri);
+      }
+    },
+    toDelete(file, model) {
+      const index = this.form[model].findIndex((f) => _.isEqual(f, file));
+      this.form[model].splice(index, 1);
+      this.$set(this, `uri`, '');
+    },
+    // 返回
+    back() {
+      this.$router.push({ path: '/patent/admin/examine/hairmess' });
+    },
+  },
+  computed: {
+    ...mapState(['user']),
+  },
+  metaInfo() {
+    return { title: this.$route.meta.title };
+  },
+  watch: {
+    test: {
+      deep: true,
+      immediate: true,
+      handler(val) {},
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped>
+.btn {
+  text-align: center;
+  .van-button {
+    margin: 10px;
+  }
+}
+.one {
+  .list {
+    background-color: #fff;
+    margin: 0 0 8px 0;
+    padding: 8px;
+    border-radius: 5px;
+    .title {
+      font-size: 16px;
+      font-weight: bold;
+      margin: 0 0 5px 0;
+    }
+    .other {
+      margin: 0 0 5px 0;
+      .otherInfo {
+        font-size: 14px;
+        color: #666;
+        margin: 0 0 5px 0;
+        span {
+          color: #000;
+        }
+      }
+    }
+  }
+}
+</style>

+ 126 - 0
src/views/patent/admin/examine/hairmess_create.vue

@@ -0,0 +1,126 @@
+<template>
+  <div id="hairmess">
+    <admin-frame topType="2" @back="back" :rightArrow="false" :usePage="false" :useNav="false">
+      <template v-slot:info>
+        <van-form>
+          <van-field name="file_url" label="文件">
+            <template #input>
+              <van-uploader
+                :fileList="form.file_url"
+                :max-count="1"
+                :after-read="(file) => toUpload(file, 'file_url')"
+                @delete="(file) => toDelete(file, 'file_url')"
+                accept="file"
+              />
+            </template>
+          </van-field>
+          <van-field v-model="form.create_number" center clearable label="专利申请号" placeholder="请输入专利申请号">
+            <template #button>
+              <van-button size="small" type="primary" @click="searchPatent">查询</van-button>
+            </template>
+          </van-field>
+          <van-field v-model="form.patent_name" name="专利名称" label="专利名称" readonly />
+          <van-field v-model="form.to_name" name="接收人" label="接收人" readonly />
+          <van-col span="24" class="btn">
+            <van-button type="danger" size="small" @click="back">取消发送</van-button>
+            <van-button type="info" size="small" @click="onSubmit">确认发送</van-button>
+          </van-col>
+        </van-form>
+      </template>
+    </admin-frame>
+  </div>
+</template>
+
+<script>
+import adminFrame from '@frame/src/components/mobile-frame/mobile-main.vue';
+import { mapState, createNamespacedHelpers } from 'vuex';
+const { mapActions: patentwarning } = createNamespacedHelpers('patentwarning');
+const { mapActions: patentapply } = createNamespacedHelpers('patentapply');
+const { mapActions: upload } = createNamespacedHelpers('upload');
+export default {
+  name: 'hairmess',
+  props: {},
+  components: {
+    adminFrame,
+  },
+  data: function () {
+    return {
+      form: {},
+    };
+  },
+  async created() {},
+  methods: {
+    ...upload(['upload']),
+    ...patentwarning(['query', 'create']),
+    ...patentapply({ patentapplyQuery: 'query' }),
+    // 确认发送
+    async onSubmit() {
+      let data = this.form;
+      let res = await this.create(data);
+      if (this.$checkRes(res)) {
+        this.$toast({ type: `success`, message: `操作成功` });
+        this.back();
+      } else {
+        this.$toast({ type: `success`, message: `${res.errmsg}` });
+      }
+    },
+    // 查询专利申请
+    async searchPatent(create_number) {
+      let info = { create_number: this.form.create_number ? this.form.create_number : create_number };
+      let res = await this.patentapplyQuery({ ...info });
+      if (this.$checkRes(res)) {
+        let data = { file_url: this.form.file_url };
+        if (res.total > 0) {
+          for (const val of res.data) {
+            data.create_number = val.create_number;
+            data.patent_id = val.id;
+            data.patent_name = val.name;
+            data.to_id = val.user_id;
+            data.to_name = val.apply_name;
+          }
+        }
+        this.$set(this, `form`, data);
+      }
+    },
+    async toUpload({ file }, model) {
+      // 上传,赋值
+      const res = await this.upload({ file, dir: 'file' });
+      if (this.$checkRes(res)) {
+        this.$set(this.form, model, [{ name: res.name, url: res.uri }]);
+        let create_number = file.name.substring(0, file.name.lastIndexOf('.'));
+        this.searchPatent(create_number);
+      }
+    },
+    toDelete(file, model) {
+      const index = this.form[model].findIndex((f) => _.isEqual(f, file));
+      this.form[model].splice(index, 1);
+    },
+    // 返回
+    back() {
+      this.$router.push({ path: '/patent/admin/examine/hairmess' });
+    },
+  },
+  computed: {
+    ...mapState(['user']),
+  },
+  metaInfo() {
+    return { title: this.$route.meta.title };
+  },
+  watch: {
+    test: {
+      deep: true,
+      immediate: true,
+      handler(val) {},
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped>
+.btn {
+  text-align: center;
+  .van-button {
+    margin: 10px;
+  }
+}
+</style>

+ 120 - 0
src/views/patent/admin/examine/patent.vue

@@ -0,0 +1,120 @@
+<template>
+  <div id="patent">
+    <admin-frame @search="search" :limit="limit" :total="total" topType="2" @back="back" :rightArrow="false" :useNav="false">
+      <template v-slot:info>
+        <list-1 :list="list" @view="view" @examine="toExamine"></list-1>
+      </template>
+    </admin-frame>
+    <van-dialog class="dialog" v-model="show" title="详细信息" :show-confirm-button="false" show-cancel-button>
+      <info-1 :info="info"></info-1>
+    </van-dialog>
+    <van-dialog class="twoDialog" v-model="twoShow" title="审核信息" :show-confirm-button="false" :show-cancel-button="false" :closeOnClickOverlay="true">
+      <check-form :form="form" @onSubmit="onSubmit"></check-form>
+    </van-dialog>
+  </div>
+</template>
+
+<script>
+import list1 from './patent/list-1.vue';
+import info1 from './patent/info-1.vue';
+import checkForm from './patent/checkForm.vue';
+import adminFrame from '@frame/src/components/mobile-frame/mobile-main.vue';
+import { mapState, createNamespacedHelpers } from 'vuex';
+const { mapActions: patentapply } = createNamespacedHelpers('patentapply');
+export default {
+  name: 'patent',
+  props: {},
+  components: {
+    adminFrame,
+    list1,
+    info1,
+    checkForm,
+  },
+  data: function () {
+    return {
+      list: [],
+      limit: 5,
+      total: 0,
+      // 专利申请详细信息
+      show: false,
+      info: {},
+      // 专利申请审核信息
+      twoShow: false,
+      form: {},
+    };
+  },
+  async created() {
+    await this.search();
+  },
+  methods: {
+    ...patentapply(['query', 'update', 'check']),
+    async search({ skip = 0, limit = this.limit, ...info } = {}) {
+      info.admin_id = this.user._id;
+      let res = await this.query({ skip, limit, ...info });
+      if (this.$checkRes(res)) {
+        this.$set(this, `list`, res.data);
+        this.$set(this, `total`, res.total);
+      }
+    },
+    // 查看
+    view(data) {
+      if (!data.questions) data.questions = {};
+      this.$set(this, `info`, data);
+      this.show = true;
+    },
+    // 审核
+    toExamine(data) {
+      this.$set(this, `form`, data);
+      this.twoShow = true;
+    },
+    // 提交审核
+    async onSubmit(data) {
+      // 申请状态修改
+      const { id, remark, status, water_number } = this.form;
+      const obj = { id, status, remark, water_number };
+      const res = await this.check(obj);
+      if (this.$checkRes(res)) {
+        this.$toast({ type: `success`, message: `审核成功` });
+        this.twoShow = false;
+      } else {
+        this.$toast({ type: `fail`, message: `${res.errmsg}` });
+      }
+    },
+    // 返回
+    back() {
+      this.$router.push({ path: '/patent/index' });
+    },
+  },
+  computed: {
+    ...mapState(['user']),
+  },
+  metaInfo() {
+    return { title: this.$route.meta.title };
+  },
+  watch: {
+    test: {
+      deep: true,
+      immediate: true,
+      handler(val) {},
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped>
+.dialog {
+  /deep/.van-dialog__content {
+    height: 350px;
+    overflow-y: auto;
+  }
+}
+.thrDialog {
+  .btn {
+    margin: 15px 0;
+    text-align: center;
+    .van-button {
+      margin: 0 10px;
+    }
+  }
+}
+</style>

+ 69 - 0
src/views/patent/admin/examine/patent/checkForm.vue

@@ -0,0 +1,69 @@
+<template>
+  <div id="checkForm">
+    <van-row>
+      <van-col span="24" class="main">
+        <van-form @submit="onSubmit">
+          <van-field v-model="form.name" name="name" label="发明名称" readonly />
+          <van-field name="status" label="审核状态">
+            <template #input>
+              <van-radio-group v-model="form.status" direction="horizontal">
+                <van-radio name="2">通过</van-radio>
+                <van-radio name="-2">拒绝</van-radio>
+              </van-radio-group>
+            </template>
+          </van-field>
+          <van-field
+            v-model="form.remark"
+            name="remark"
+            rows="8"
+            autosize
+            label="审核意见"
+            type="textarea"
+            maxlength="100"
+            placeholder="审核意见"
+            show-word-limit
+            :rules="[{ required: true, message: '特殊情况说明' }]"
+          />
+          <div style="margin: 16px">
+            <van-button round block type="info" native-type="submit">提交</van-button>
+          </div>
+        </van-form>
+      </van-col>
+    </van-row>
+  </div>
+</template>
+
+<script>
+import { mapState, createNamespacedHelpers } from 'vuex';
+export default {
+  name: 'checkForm',
+  props: {
+    form: { type: Object },
+  },
+  components: {},
+  data: function () {
+    return {};
+  },
+  created() {},
+  methods: {
+    onSubmit(values) {
+      this.$emit('onSubmit', values);
+    },
+  },
+  computed: {
+    ...mapState(['user']),
+  },
+  metaInfo() {
+    return { title: this.$route.meta.title };
+  },
+  watch: {
+    test: {
+      deep: true,
+      immediate: true,
+      handler(val) {},
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped></style>

+ 96 - 0
src/views/patent/admin/examine/patent/info-1.vue

@@ -0,0 +1,96 @@
+<template>
+  <div id="info-1">
+    <van-row>
+      <van-col span="24" class="main">
+        <van-form>
+          <van-field v-model="info.name" name="发明名称" label="发明名称" readonly />
+          <van-field v-model="info.apply_name" name="申请人" label="申请人" readonly />
+          <van-field v-model="info.type" name="专利类型" label="专利类型" readonly />
+          <van-col span="24" class="other">
+            <span>发明人:</span><span v-for="(item, index) in info.inventor" :key="index">{{ item.name }};</span>
+          </van-col>
+          <van-col span="24" class="other">
+            <span>技术联系人:</span><span v-for="(item, index) in info.contact" :key="index">{{ item.name }};</span>
+          </van-col>
+          <van-field v-model="info.phone" name="联系人电话" label="联系人电话" readonly />
+          <van-field v-model="info.email" name="联系人邮箱" label="联系人邮箱" readonly />
+          <van-field v-model="info.questions.q8" type="textarea" rows="1" autosize name="特殊情况说明" label="特殊情况说明" readonly />
+          <van-field v-model="info.questions.q1" type="textarea" rows="1" autosize name="本发明的技术领域" label="本发明的技术领域" readonly />
+          <van-field v-model="info.questions.q2" type="textarea" rows="1" autosize name="与本发明相关的背景技术" label="与本发明相关的背景技术" readonly />
+          <van-field
+            v-model="info.questions.q3"
+            type="textarea"
+            rows="1"
+            autosize
+            name="现有技术的缺点及本发明所要解决的技术问题"
+            label="现有技术的缺点及本发明所要解决的技术问题"
+            readonly
+          />
+          <van-field v-model="info.questions.q4" type="textarea" rows="1" autosize name="本发明技术方案的详细阐述" label="本发明技术方案的详细阐述" readonly />
+          <van-field v-model="info.questions.q5" type="textarea" rows="1" autosize name="本申请的关键点和欲保护点" label="本申请的关键点和欲保护点" readonly />
+          <van-field
+            v-model="info.questions.q6"
+            type="textarea"
+            rows="1"
+            autosize
+            name="与本发明最相似,相近的实现技术,方案相比,本发明有何优点"
+            label="与本发明最相似,相近的实现技术,方案相比,本发明有何优点"
+            readonly
+          />
+          <van-field
+            v-model="info.questions.q7"
+            type="textarea"
+            rows="1"
+            autosize
+            name="针对本发明技术方案,是否还有别的替代方案"
+            label="针对本发明技术方案,是否还有别的替代方案"
+            readonly
+          />
+        </van-form>
+      </van-col>
+    </van-row>
+  </div>
+</template>
+
+<script>
+import { mapState, createNamespacedHelpers } from 'vuex';
+export default {
+  name: 'info-1',
+  props: {
+    info: { type: Object },
+  },
+  components: {},
+  data: function () {
+    return {};
+  },
+  created() {},
+  methods: {},
+  computed: {
+    ...mapState(['user']),
+  },
+  metaInfo() {
+    return { title: this.$route.meta.title };
+  },
+  watch: {
+    test: {
+      deep: true,
+      immediate: true,
+      handler(val) {},
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped>
+.other {
+  background-color: #ffffff;
+  padding: 8px 18px;
+  span {
+    color: #666;
+    font-size: 15px;
+  }
+  span:last-child {
+    color: #000;
+  }
+}
+</style>

+ 124 - 0
src/views/patent/admin/examine/patent/list-1.vue

@@ -0,0 +1,124 @@
+<template>
+  <div id="list-1">
+    <van-row>
+      <van-col span="24" class="main">
+        <van-col span="24" class="list" v-for="(item, index) in list" :key="index">
+          <van-col span="24" class="title textOver">
+            {{ item.name }}
+          </van-col>
+          <van-col span="24" class="other">
+            <van-col span="24" class="otherInfo">
+              专利用户码:<span>{{ item.water_number || '暂无' }}</span>
+            </van-col>
+            <van-col span="24" class="otherInfo">
+              申请号:<span>{{ item.create_number || '暂无' }}</span>
+            </van-col>
+            <van-col span="24" class="otherInfo">
+              申请人:<span>{{ item.apply_name || '暂无' }}</span>
+            </van-col>
+            <van-col span="24" class="otherInfo">
+              申请类型:<span>{{ item.type || '暂无' }}</span>
+            </van-col>
+            <van-col span="24" class="otherInfo">
+              申请状态:<span>{{ getStu(item.status) }}</span>
+            </van-col>
+          </van-col>
+          <van-col span="24" class="btn">
+            <van-button size="small" type="info" @click="view(item)">查看信息</van-button>
+            <van-button size="small" type="info" @click="download(item)">审查文件下载</van-button>
+            <van-button size="small" type="info" @click="examine(item)" v-if="item.status == '1'">审核申请</van-button>
+          </van-col>
+        </van-col>
+      </van-col>
+    </van-row>
+  </div>
+</template>
+
+<script>
+import { mapState, createNamespacedHelpers } from 'vuex';
+export default {
+  name: 'list-1',
+  props: {
+    list: { type: Array },
+  },
+  components: {},
+  data: function () {
+    return {};
+  },
+  created() {},
+  methods: {
+    // 查看详情
+    view(data) {
+      this.$emit('view', data);
+    },
+    // 审核专利
+    examine(data) {
+      this.$emit('examine', data);
+    },
+    // 整理状态
+    getStu(status) {
+      if (status == '0') return '已提交给相应机构,请等待审核';
+      else if (status == '1') return '机构审核通过,已提交给管理员,请等待审核';
+      else if (status == '-1') return '机构审核未通过,请查看审核意见,并重新提交申请';
+      else if (status == '2') return '管理员审核通过';
+      else if (status == '-2') return '管理员审核未通过,请查看审核意见,并重新提交申请';
+    },
+    // 审查文件下载
+    download(data) {
+      if (data.check_url.length > 0) {
+        let url = data.check_url.map((i) => i.url);
+        window.location.href = `${process.env.VUE_APP_HOST}/${url[0]}`;
+      } else {
+        this.$toast({ type: `fail`, message: `未上传文件` });
+      }
+    },
+  },
+  computed: {
+    ...mapState(['user']),
+  },
+  metaInfo() {
+    return { title: this.$route.meta.title };
+  },
+  watch: {
+    test: {
+      deep: true,
+      immediate: true,
+      handler(val) {},
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped>
+.main {
+  padding: 8px 8px 0 8px;
+  .list {
+    background-color: #fff;
+    margin: 0 0 8px 0;
+    padding: 8px;
+    border-radius: 5px;
+    .title {
+      font-size: 16px;
+      font-weight: bold;
+      margin: 0 0 5px 0;
+    }
+    .other {
+      margin: 0 0 5px 0;
+      .otherInfo {
+        font-size: 14px;
+        color: #666;
+        margin: 0 0 5px 0;
+        span {
+          color: #000;
+        }
+      }
+    }
+    .btn {
+      text-align: center;
+      .van-button {
+        margin: 5px;
+      }
+    }
+  }
+}
+</style>

+ 72 - 0
src/views/patent/admin/message/examine.vue

@@ -0,0 +1,72 @@
+<template>
+  <div id="read">
+    <admin-frame @search="search" :limit="limit" :total="total" topType="2" @back="back" :rightArrow="false" :useNav="false">
+      <template v-slot:info>
+        <list-3 :list="list" @update="toUpdate"></list-3>
+      </template>
+    </admin-frame>
+  </div>
+</template>
+
+<script>
+import list3 from './parts/list-3.vue';
+import adminFrame from '@frame/src/components/mobile-frame/mobile-main.vue';
+import { mapState, createNamespacedHelpers } from 'vuex';
+const { mapActions: patentexamine } = createNamespacedHelpers('patentexamine');
+export default {
+  name: 'read',
+  props: {},
+  components: {
+    adminFrame,
+    list3,
+  },
+  data: function () {
+    return {
+      limit: 5,
+      total: 0,
+      list: [],
+    };
+  },
+  async created() {
+    this.search();
+  },
+  methods: {
+    ...patentexamine(['query', 'update']),
+    async search({ skip = 0, limit = this.limit, ...info } = {}) {
+      info.to = this.user.id;
+      let res = await this.query({ skip, limit, ...info });
+      if (this.$checkRes(res)) {
+        this.$set(this, `list`, res.data);
+        this.$set(this, `total`, res.total);
+      }
+    },
+    async toUpdate(data) {
+      data.is_read = true;
+      let res = await this.update(data);
+      if (this.$checkRes(res)) {
+        this.$toast({ type: 'success', message: '取消提醒成功' });
+        this.search();
+      }
+    },
+    // 返回
+    back() {
+      this.$router.push({ path: '/patent/index' });
+    },
+  },
+  computed: {
+    ...mapState(['user']),
+  },
+  metaInfo() {
+    return { title: this.$route.meta.title };
+  },
+  watch: {
+    test: {
+      deep: true,
+      immediate: true,
+      handler(val) {},
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped></style>

+ 67 - 0
src/views/patent/admin/message/notice.vue

@@ -0,0 +1,67 @@
+<template>
+  <div id="read">
+    <admin-frame @search="search" :limit="limit" :total="total" topType="2" @back="back" @add="add" :useNav="false">
+      <template v-slot:info>
+        <list-2 :list="list"></list-2>
+      </template>
+    </admin-frame>
+  </div>
+</template>
+
+<script>
+import list2 from './parts/list-2.vue';
+import adminFrame from '@frame/src/components/mobile-frame/mobile-main.vue';
+import { mapState, createNamespacedHelpers } from 'vuex';
+const { mapActions: patentnotice } = createNamespacedHelpers('patentnotice');
+export default {
+  name: 'read',
+  props: {},
+  components: {
+    adminFrame,
+    list2,
+  },
+  data: function () {
+    return {
+      limit: 5,
+      total: 0,
+      list: [],
+    };
+  },
+  async created() {
+    this.search();
+  },
+  methods: {
+    ...patentnotice(['query']),
+    async search({ skip = 0, limit = this.limit, ...info } = {}) {
+      let res = await this.query({ skip, limit, ...info });
+      if (this.$checkRes(res)) {
+        this.$set(this, `list`, res.data);
+        this.$set(this, `total`, res.total);
+      }
+    },
+    // 添加
+    add() {
+      this.$router.push({ path: '/patent/admin/message/notice_create' });
+    },
+    // 返回
+    back() {
+      this.$router.push({ path: '/patent/index' });
+    },
+  },
+  computed: {
+    ...mapState(['user']),
+  },
+  metaInfo() {
+    return { title: this.$route.meta.title };
+  },
+  watch: {
+    test: {
+      deep: true,
+      immediate: true,
+      handler(val) {},
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped></style>

+ 79 - 0
src/views/patent/admin/message/notice_create.vue

@@ -0,0 +1,79 @@
+<template>
+  <div id="notice_create">
+    <admin-frame topType="2" @back="back" :rightArrow="false" :usePage="false" :useNav="false">
+      <template v-slot:info>
+        <notice-form :form="form" @onSubmit="onSubmit"></notice-form>
+      </template>
+    </admin-frame>
+  </div>
+</template>
+
+<script>
+import noticeForm from './parts/form-1.vue';
+import adminFrame from '@frame/src/components/mobile-frame/mobile-main.vue';
+import { mapState, createNamespacedHelpers } from 'vuex';
+const { mapActions: patentnotice } = createNamespacedHelpers('patentnotice');
+export default {
+  name: 'detail',
+  props: {},
+  components: {
+    adminFrame,
+    noticeForm,
+  },
+  data: function () {
+    return {
+      form: {},
+    };
+  },
+  async created() {
+    this.search();
+  },
+  methods: {
+    ...patentnotice(['create']),
+    search() {
+      let data = { send_id: this.user.id, send_name: this.user.name };
+      this.$set(this, `form`, data);
+    },
+    async onSubmit(data) {
+      let res = await this.create(data);
+      if (this.$checkRes(res)) {
+        this.$toast({ type: `success`, message: `发送通知成功` });
+        this.back();
+      } else {
+        this.$toast({ type: `success`, message: `${res.errmsg}` });
+      }
+    },
+    // 返回
+    back() {
+      this.$router.push({ path: '/patent/admin/message/notice' });
+    },
+  },
+  computed: {
+    ...mapState(['user']),
+    id() {
+      return this.$route.query.id;
+    },
+  },
+  metaInfo() {
+    return { title: this.$route.meta.title };
+  },
+  watch: {
+    test: {
+      deep: true,
+      immediate: true,
+      handler(val) {},
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped>
+.one {
+  .one_1 {
+    text-align: center;
+    .van-button {
+      margin: 0 5px 10px 5px;
+    }
+  }
+}
+</style>

+ 60 - 0
src/views/patent/admin/message/parts/form-1.vue

@@ -0,0 +1,60 @@
+<template>
+  <div id="form-1">
+    <van-row>
+      <van-col span="24" class="main">
+        <van-form @submit="onSubmit" label-width="4em">
+          <van-field v-model="form.send_id" name="send_id" label="发送人id" style="display: none" />
+          <van-field v-model="form.send_name" name="send_name" label="发送人" readonly />
+          <van-field name="to_type" label="接收用户">
+            <template #input>
+              <van-radio-group v-model="form.to_type" direction="horizontal">
+                <van-radio name="0">所有用户</van-radio>
+                <van-radio name="1">机构用户</van-radio>
+                <van-radio name="2">平台用户</van-radio>
+              </van-radio-group>
+            </template>
+          </van-field>
+          <van-field v-model="form.content" name="content" rows="2" autosize label="发送内容" type="textarea" placeholder="发送内容" />
+          <div style="margin: 16px">
+            <van-button round block type="info" native-type="submit">提交</van-button>
+          </div>
+        </van-form>
+      </van-col>
+    </van-row>
+  </div>
+</template>
+
+<script>
+import { mapState, createNamespacedHelpers } from 'vuex';
+export default {
+  name: 'form-1',
+  props: {
+    form: { type: Object },
+  },
+  components: {},
+  data: function () {
+    return {};
+  },
+  created() {},
+  methods: {
+    onSubmit(values) {
+      this.$emit('onSubmit', values);
+    },
+  },
+  computed: {
+    ...mapState(['user']),
+  },
+  metaInfo() {
+    return { title: this.$route.meta.title };
+  },
+  watch: {
+    test: {
+      deep: true,
+      immediate: true,
+      handler(val) {},
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped></style>

+ 99 - 0
src/views/patent/admin/message/parts/list-1.vue

@@ -0,0 +1,99 @@
+<template>
+  <div id="list-1">
+    <van-row>
+      <van-col span="24" class="main">
+        <van-col span="24" class="list" v-for="(item, index) in list" :key="index">
+          <van-col span="24" class="name">
+            {{ getName(item) }}
+          </van-col>
+          <van-col span="24" class="other">
+            <van-col span="24" class="otherInfo"> 发送时间:{{ item.send_time || '暂无' }} </van-col>
+            <van-col span="24" class="otherInfo textOver"> 发送内容:{{ item.type == '1' ? item.content : '文件' }} </van-col>
+          </van-col>
+          <van-col span="24" class="btn">
+            <van-button type="info" size="small" @click="detail(item)">查看消息</van-button>
+          </van-col>
+        </van-col>
+      </van-col>
+    </van-row>
+  </div>
+</template>
+
+<script>
+import { mapState, createNamespacedHelpers } from 'vuex';
+export default {
+  name: 'list-1',
+  props: {
+    list: { type: Array },
+  },
+  components: {},
+  data: function () {
+    return {
+      otherInfo: {},
+    };
+  },
+  created() {},
+  methods: {
+    detail(data) {
+      if (data.sender_id == this.user._id) {
+        this.$set(this, `otherInfo`, { sender_id: data.receiver_id, sender_name: data.receiver_name });
+      } else {
+        this.$set(this, `otherInfo`, { sender_id: data.sender_id, sender_name: data.sender_name });
+      }
+      this.$router.push({ path: '/service/patent/admin/message/service_detail', query: { ...this.otherInfo } });
+    },
+    // 整理名称
+    getName(data) {
+      if (data.sender_id == this.user._id) return data.receiver_name;
+      else return data.sender_name;
+    },
+  },
+  computed: {
+    ...mapState(['user']),
+  },
+  metaInfo() {
+    return { title: this.$route.meta.title };
+  },
+  watch: {
+    test: {
+      deep: true,
+      immediate: true,
+      handler(val) {},
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped>
+.main {
+  padding: 8px 8px 0 8px;
+  .list {
+    background-color: #fff;
+    margin: 0 0 8px 0;
+    padding: 8px;
+    border-radius: 5px;
+    .title {
+      font-size: 16px;
+      font-weight: bold;
+      margin: 0 0 5px 0;
+    }
+    .other {
+      margin: 0 0 5px 0;
+      .otherInfo {
+        font-size: 14px;
+        color: #666;
+        margin: 0 0 5px 0;
+        span {
+          color: #000;
+        }
+      }
+    }
+    .btn {
+      text-align: center;
+      .van-button {
+        margin: 0 5px;
+      }
+    }
+  }
+}
+</style>

+ 92 - 0
src/views/patent/admin/message/parts/list-2.vue

@@ -0,0 +1,92 @@
+<template>
+  <div id="list-2">
+    <van-col span="24" class="main">
+      <van-col span="24" class="list" v-for="(item, index) in list" :key="index">
+        <van-col span="24" class="other">
+          <van-col span="24" class="otherInfo">
+            <span>{{ item.content || '暂无' }}</span>
+          </van-col>
+          <van-col span="24" class="otherInfo">
+            发送人:<span>{{ item.send_name || '暂无' }}</span>
+          </van-col>
+          <van-col span="24" class="otherInfo">
+            发送时间:<span>{{ getDate(item.meta) }}</span>
+          </van-col>
+        </van-col>
+      </van-col>
+    </van-col>
+  </div>
+</template>
+
+<script>
+import { mapState, createNamespacedHelpers } from 'vuex';
+var moment = require('moment');
+export default {
+  name: 'list-2',
+  props: {
+    list: { type: Array },
+  },
+  components: {},
+  data: function () {
+    return {};
+  },
+  created() {},
+  methods: {
+    update(data) {
+      this.$emit('update', data);
+    },
+    getDate(val) {
+      let newDate = moment(val.createdAt).format('YYYY-MM-DD HH:mm:ss');
+      if (newDate) return newDate;
+    },
+  },
+  computed: {
+    ...mapState(['user']),
+  },
+  metaInfo() {
+    return { title: this.$route.meta.title };
+  },
+  watch: {
+    test: {
+      deep: true,
+      immediate: true,
+      handler(val) {},
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped>
+.main {
+  padding: 8px 0 0 0;
+  .list {
+    background-color: #fff;
+    margin: 0 0 8px 0;
+    padding: 8px;
+    border-radius: 5px;
+    .title {
+      font-size: 16px;
+      font-weight: bold;
+      margin: 0 0 5px 0;
+    }
+    .other {
+      margin: 0 0 5px 0;
+      .otherInfo {
+        font-size: 14px;
+        color: #666;
+        margin: 0 0 5px 0;
+        span {
+          color: #000;
+          line-height: 20px;
+        }
+      }
+    }
+    .btn {
+      text-align: center;
+      .van-button {
+        margin: 0 5px;
+      }
+    }
+  }
+}
+</style>

+ 95 - 0
src/views/patent/admin/message/parts/list-3.vue

@@ -0,0 +1,95 @@
+<template>
+  <div id="list-1">
+    <van-col span="24" class="main">
+      <van-col span="24" class="list" v-for="(item, index) in list" :key="index">
+        <van-col span="24" class="other">
+          <van-col span="24" class="otherInfo">
+            <span>{{ item.content || '暂无' }}</span>
+          </van-col>
+          <van-col span="24" class="otherInfo">
+            发送时间:<span>{{ getDate(item.meta) }}</span>
+          </van-col>
+          <van-col span="24" class="otherInfo">
+            是否已读:<span>{{ item.is_read ? '已读' : '未读' }}</span>
+          </van-col>
+        </van-col>
+        <van-col span="24" class="btn" v-if="item.is_read == false">
+          <van-button size="small" type="info" @click="update(item)">消息已读</van-button>
+        </van-col>
+      </van-col>
+    </van-col>
+  </div>
+</template>
+
+<script>
+import { mapState, createNamespacedHelpers } from 'vuex';
+var moment = require('moment');
+export default {
+  name: 'list-1',
+  props: {
+    list: { type: Array },
+  },
+  components: {},
+  data: function () {
+    return {};
+  },
+  created() {},
+  methods: {
+    update(data) {
+      this.$emit('update', data);
+    },
+    getDate(val) {
+      let newDate = moment(val.createdAt).format('YYYY-MM-DD HH:mm:ss');
+      if (newDate) return newDate;
+    },
+  },
+  computed: {
+    ...mapState(['user']),
+  },
+  metaInfo() {
+    return { title: this.$route.meta.title };
+  },
+  watch: {
+    test: {
+      deep: true,
+      immediate: true,
+      handler(val) {},
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped>
+.main {
+  padding: 8px 0 0 0;
+  .list {
+    background-color: #fff;
+    margin: 0 0 8px 0;
+    padding: 8px;
+    border-radius: 5px;
+    .title {
+      font-size: 16px;
+      font-weight: bold;
+      margin: 0 0 5px 0;
+    }
+    .other {
+      margin: 0 0 5px 0;
+      .otherInfo {
+        font-size: 14px;
+        color: #666;
+        margin: 0 0 5px 0;
+        span {
+          color: #000;
+          line-height: 20px;
+        }
+      }
+    }
+    .btn {
+      text-align: center;
+      .van-button {
+        margin: 0 5px;
+      }
+    }
+  }
+}
+</style>

+ 83 - 0
src/views/patent/admin/message/parts/list-4.vue

@@ -0,0 +1,83 @@
+<template>
+  <div id="list-4">
+    <van-col span="24" class="main">
+      <van-col span="24" class="list" v-for="(item, index) in list" :key="index">
+        <van-col span="24" class="other">
+          <van-col span="24" class="otherInfo">
+            <span>{{ item.name || '暂无' }}</span>
+          </van-col>
+          <van-col span="24" class="otherInfo">
+            专利失效日期:<span>{{ item.lose_date || '暂无' }}</span>
+          </van-col>
+          <van-col span="24" class="otherInfo">
+            预警信息:<span>{{ item.content }}</span>
+          </van-col>
+        </van-col>
+      </van-col>
+    </van-col>
+  </div>
+</template>
+
+<script>
+import { mapState, createNamespacedHelpers } from 'vuex';
+export default {
+  name: 'list-4',
+  props: {
+    list: { type: Array },
+  },
+  components: {},
+  data: function () {
+    return {};
+  },
+  created() {},
+  methods: {},
+  computed: {
+    ...mapState(['user']),
+  },
+  metaInfo() {
+    return { title: this.$route.meta.title };
+  },
+  watch: {
+    test: {
+      deep: true,
+      immediate: true,
+      handler(val) {},
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped>
+.main {
+  padding: 8px 0 0 0;
+  .list {
+    background-color: #fff;
+    margin: 0 0 8px 0;
+    padding: 8px;
+    border-radius: 5px;
+    .title {
+      font-size: 16px;
+      font-weight: bold;
+      margin: 0 0 5px 0;
+    }
+    .other {
+      margin: 0 0 5px 0;
+      .otherInfo {
+        font-size: 14px;
+        color: #666;
+        margin: 0 0 5px 0;
+        span {
+          color: #000;
+          line-height: 20px;
+        }
+      }
+    }
+    .btn {
+      text-align: center;
+      .van-button {
+        margin: 0 5px;
+      }
+    }
+  }
+}
+</style>

+ 68 - 0
src/views/patent/admin/message/service.vue

@@ -0,0 +1,68 @@
+<template>
+  <div id="service">
+    <admin-frame @search="search" :limit="limit" :total="total" topType="2" @back="back" :rightArrow="false" :useNav="false">
+      <template v-slot:info>
+        <list-1 :list="list"></list-1>
+      </template>
+    </admin-frame>
+  </div>
+</template>
+
+<script>
+import list1 from './parts/list-1.vue';
+import adminFrame from '@frame/src/components/mobile-frame/mobile-main.vue';
+import { mapState, createNamespacedHelpers } from 'vuex';
+const { mapActions: patentchat } = createNamespacedHelpers('patentchat');
+export default {
+  name: 'service',
+  props: {},
+  components: {
+    adminFrame,
+    list1,
+  },
+  data: function () {
+    return {
+      list: [
+        {
+          name: '发送人',
+        },
+      ],
+      limit: 5,
+      total: 0,
+    };
+  },
+  async created() {
+    await this.search();
+  },
+  methods: {
+    ...patentchat(['adminQuery']),
+    async search({ skip = 0, limit = this.limit, ...info } = {}) {
+      info.id = this.user._id;
+      let res = await this.adminQuery({ skip, limit, ...info });
+      if (this.$checkRes(res)) {
+        this.$set(this, `list`, res.data);
+        this.$set(this, `total`, res.total);
+      }
+    },
+    // 返回
+    back() {
+      this.$router.push({ path: '/patent/index' });
+    },
+  },
+  computed: {
+    ...mapState(['user']),
+  },
+  metaInfo() {
+    return { title: this.$route.meta.title };
+  },
+  watch: {
+    test: {
+      deep: true,
+      immediate: true,
+      handler(val) {},
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped></style>

+ 287 - 0
src/views/patent/admin/message/service_detail.vue

@@ -0,0 +1,287 @@
+<template>
+  <div id="service_detail">
+    <admin-frame topType="2" @back="back" :rightArrow="false" :usePage="false" :useNav="false">
+      <template v-slot:info>
+        <van-col span="24" class="one" :style="{ height: getHeight() }">
+          <template v-for="(i, index) in list">
+            <template v-if="isSender(i, index)">
+              <van-col span="24" class="senderTime" :key="`div${i.id}${index}`">
+                <span :key="`senderTime${i.id}${index}`">[{{ i.send_time }}] {{ i.sender_name }}</span>
+                <span v-if="i.type == '1'" v-html="i.content" :key="`senderContent${i.id}${index}`"></span>
+                <span v-else-if="i.type == '2'">
+                  {{ getFile(i.file) }}<van-button type="info" size="mini" class="downBtn" @click="downFile(i.file)">下载</van-button>
+                </span>
+              </van-col>
+            </template>
+            <template v-else>
+              <van-col span="24" class="receverTime" :key="`div${i.id}${index}`">
+                <span :key="`receverTime${i.id}${index}`"> {{ i.sender_name }} [{{ i.send_time }}]</span>
+                <span v-if="i.type == '1'" v-html="i.content" :key="`receverContent${i.id}${index}`"></span>
+                <span v-else-if="i.type == '2'">
+                  {{ getFile(i.file) }}<van-button type="info" size="mini" class="downBtn" @click="downFile(i.file)">下载</van-button>
+                </span>
+              </van-col>
+            </template>
+          </template>
+        </van-col>
+        <van-col span="24" class="two">
+          <van-col span="17" class="cont">
+            <van-field v-model="content" placeholder="请输入内容" />
+          </van-col>
+          <van-col span="7" class="btn">
+            <van-button type="info" size="small" @click="send">发送</van-button>
+            <van-button type="info" size="small" @click="other">其它</van-button>
+          </van-col>
+        </van-col>
+      </template>
+    </admin-frame>
+    <van-dialog v-model="show" class="dialog" title="文件" :showConfirmButton="false" :showCancelButton="false" :closeOnClickOverlay="false">
+      <van-form>
+        <van-field name="file" label="文件">
+          <template #input>
+            <van-uploader
+              :fileList="fileForm.file"
+              :max-count="1"
+              :after-read="(file) => toUpload(file, 'file')"
+              @delete="(file) => toDelete(file, 'file')"
+              accept="file"
+            />
+          </template>
+        </van-field>
+        <div class="btn">
+          <van-button type="danger" size="small" @click="twoClose">取消发送</van-button>
+          <van-button type="info" size="small" @click="twoSend">提交发送</van-button>
+        </div>
+      </van-form>
+    </van-dialog>
+  </div>
+</template>
+
+<script>
+import adminFrame from '@frame/src/components/mobile-frame/mobile-main.vue';
+import { mapState, createNamespacedHelpers } from 'vuex';
+const { mapActions: upload } = createNamespacedHelpers('upload');
+const { mapActions: patentchat } = createNamespacedHelpers('patentchat');
+export default {
+  name: 'service_detail',
+  props: {},
+  components: {
+    adminFrame,
+  },
+  data: function () {
+    return {
+      client: {},
+      list: [],
+      content: '',
+      // 发送其他内容
+      show: false,
+      fileForm: {},
+    };
+  },
+  async created() {
+    await this.search();
+  },
+  methods: {
+    ...upload(['upload']),
+    ...patentchat(['adminChatQuery', 'create']),
+    async search() {
+      let res = await this.adminChatQuery({ sender_id: this.sender_id, receiver_id: this.user._id });
+      if (this.$checkRes(res)) {
+        this.$set(this, `list`, res.data);
+      }
+    },
+    // 发言
+    async send() {
+      if (this.content) {
+        let data = {
+          type: '1',
+          content: this.content,
+          sender_id: this.user._id,
+          sender_name: this.user.name,
+          receiver_id: this.sender_id,
+          receiver_name: this.sender_name,
+        };
+        let res = await this.create(data);
+        if (this.$checkRes(res)) {
+          this.$toast({ type: `success`, message: `发言成功` });
+          this.content = '';
+          this.search();
+        }
+      } else {
+        this.$toast({ type: `fail`, message: `缺少必要信息` });
+      }
+    },
+    // 发言,发送文件
+    other() {
+      this.show = true;
+    },
+    // 提交发送
+    async twoSend() {
+      let data = this.fileForm;
+      if (data.file) {
+        let arr = {
+          type: '2',
+          file: data.file,
+          sender_id: this.user._id,
+          sender_name: this.user.name,
+          receiver_id: this.sender_id,
+          receiver_name: this.sender_name,
+        };
+        let res = await this.create(arr);
+        if (this.$checkRes(res)) {
+          this.$toast({ type: `success`, message: `发言成功` });
+          this.fileForm = { file: [] };
+          this.twoClose();
+          this.search();
+        }
+      } else {
+        this.$toast({ type: `fail`, message: `缺少必要信息` });
+      }
+    },
+    // 取消发送
+    twoClose() {
+      this.show = false;
+    },
+
+    async toUpload({ file }, model) {
+      // 上传,赋值
+      const res = await this.upload({ file, dir: 'chat' });
+      if (this.$checkRes(res)) {
+        this.$set(this.fileForm, model, [{ name: res.name, url: res.uri }]);
+      }
+    },
+    toDelete(file, model) {
+      const index = this.fileForm[model].findIndex((f) => _.isEqual(f, file));
+      this.fileForm[model].splice(index, 1);
+    },
+    // 处理文件
+    getFile(data) {
+      if (data.length > 0) {
+        return data[0].name;
+      }
+    },
+    // 下载文件
+    downFile(data) {
+      if (data.length > 0) {
+        let url = data.map((i) => i.url);
+        window.location.href = `${process.env.VUE_APP_HOST}/${url[0]}`;
+      } else {
+        this.$toast({ type: `fail`, message: `非正常文件,无法下载` });
+      }
+    },
+    // 判断发言人
+    isSender(data) {
+      return this.user.id !== data.sender_id;
+    },
+    // 返回
+    back() {
+      this.$router.push({ path: '/patent/admin/message/service' });
+    },
+    // 计算高度
+    getHeight() {
+      let windowH = this.client.height - 87;
+      return windowH + 'px';
+    },
+  },
+  computed: {
+    ...mapState(['user']),
+    sender_id() {
+      return this.$route.query.sender_id;
+    },
+    sender_name() {
+      return this.$route.query.sender_name;
+    },
+  },
+  mounted() {
+    let client = {
+      height: document.documentElement.clientHeight || document.body.clientHeight,
+      width: document.documentElement.clientWidth || document.body.clientWidth,
+    };
+    this.$set(this, `client`, client);
+  },
+  metaInfo() {
+    return { title: this.$route.meta.title };
+  },
+  watch: {
+    test: {
+      deep: true,
+      immediate: true,
+      handler(val) {},
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped>
+.main {
+  .one {
+    overflow-x: hidden;
+    overflow-y: auto;
+    padding: 10px 5px;
+    .senderTime {
+      float: left;
+      width: 100%;
+      text-align: left;
+      color: #666;
+      font-size: 14px;
+      margin: 0 0 5px 0;
+    }
+    .senderTime span:last-child {
+      float: left;
+      width: 100%;
+      text-align: left;
+      color: #000;
+    }
+    .receverTime {
+      float: right;
+      width: 100%;
+      color: #666;
+      font-size: 14px;
+      margin: 0 0 5px 0;
+    }
+    .receverTime span:first-child {
+      float: right;
+      width: 100%;
+      text-align: right;
+    }
+    .receverTime span:last-child {
+      float: right;
+      width: 100%;
+      text-align: right;
+      color: #000;
+    }
+  }
+  .two {
+    height: 40px;
+    border-top: 1px solid #ccc;
+    .cont {
+      /deep/.van-cell {
+        line-height: 20px;
+        padding: 10px;
+      }
+    }
+    .btn {
+      text-align: center;
+      /deep/.van-button--small {
+        width: 54px;
+        height: 40px;
+        padding: 0;
+      }
+    }
+  }
+}
+.dialog {
+  .btn {
+    text-align: center;
+    .van-button {
+      margin: 8px;
+    }
+  }
+}
+.downBtn {
+  margin: 0 0 0 8px;
+  /deep/.van-button__text {
+    color: #ffffff !important;
+  }
+}
+</style>

+ 64 - 0
src/views/patent/admin/message/warning.vue

@@ -0,0 +1,64 @@
+<template>
+  <div id="read">
+    <admin-frame @search="search" :limit="limit" :total="total" topType="2" @back="back" :rightArrow="false" :useNav="false">
+      <template v-slot:info>
+        <list-4 :list="list"></list-4>
+      </template>
+    </admin-frame>
+  </div>
+</template>
+
+<script>
+import list4 from './parts/list-4.vue';
+import adminFrame from '@frame/src/components/mobile-frame/mobile-main.vue';
+import { mapState, createNamespacedHelpers } from 'vuex';
+const { mapActions: patentearly } = createNamespacedHelpers('patentearly');
+export default {
+  name: 'read',
+  props: {},
+  components: {
+    adminFrame,
+    list4,
+  },
+  data: function () {
+    return {
+      limit: 5,
+      total: 0,
+      list: [],
+    };
+  },
+  async created() {
+    this.search();
+  },
+  methods: {
+    ...patentearly(['query']),
+    async search({ skip = 0, limit = this.limit, searchName, ...info } = {}) {
+      info.searchName = searchName;
+      let res = await this.query({ skip, limit, ...info });
+      if (this.$checkRes(res)) {
+        this.$set(this, `list`, res.data);
+        this.$set(this, `total`, res.total);
+      }
+    },
+    // 返回
+    back() {
+      this.$router.push({ path: '/patent/index' });
+    },
+  },
+  computed: {
+    ...mapState(['user']),
+  },
+  metaInfo() {
+    return { title: this.$route.meta.title };
+  },
+  watch: {
+    test: {
+      deep: true,
+      immediate: true,
+      handler(val) {},
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped></style>

+ 157 - 0
src/views/patent/admin/patent/assessment.vue

@@ -0,0 +1,157 @@
+<template>
+  <div id="assessment">
+    <admin-frame @search="search" :limit="limit" :total="total" topType="2" @back="back" :rightArrow="false" :useNav="false">
+      <template v-slot:info>
+        <list-1 :list="list" @examine="toExamine" @view="toView" @toFile="toFile"></list-1>
+      </template>
+    </admin-frame>
+    <van-dialog class="dialog" v-model="show" title="详细信息" :show-confirm-button="false" show-cancel-button>
+      <info-1 :info="info"></info-1>
+    </van-dialog>
+    <van-dialog class="thrDialog" v-model="thrShow" title="报告文件" :show-confirm-button="false" :show-cancel-button="false" :closeOnClickOverlay="true">
+      <van-form>
+        <van-field name="report" label="文件">
+          <template #input>
+            <van-uploader
+              :fileList="fileForm.report"
+              :max-count="1"
+              :after-read="(file) => toUpload(file, 'report')"
+              @delete="(file) => toDelete(file, 'report')"
+              accept="file"
+            />
+          </template>
+        </van-field>
+        <div class="btn">
+          <van-button type="danger" size="small" @click="thrClose">取消发送</van-button>
+          <van-button type="info" size="small" @click="thrSend">提交发送</van-button>
+        </div>
+      </van-form>
+    </van-dialog>
+  </div>
+</template>
+
+<script>
+import list1 from './assessment/list-1.vue';
+import info1 from './assessment/info-1.vue';
+import adminFrame from '@frame/src/components/mobile-frame/mobile-main.vue';
+import { mapState, createNamespacedHelpers } from 'vuex';
+const { mapActions: patentassess } = createNamespacedHelpers('patentassess');
+const { mapActions: patentinfo } = createNamespacedHelpers('patentinfo');
+const { mapActions: upload } = createNamespacedHelpers('upload');
+export default {
+  name: 'assessment',
+  props: {},
+  components: {
+    adminFrame,
+    list1,
+    info1,
+  },
+  data: function () {
+    return {
+      list: [],
+      limit: 5,
+      total: 0,
+      // 专利详情
+      show: false,
+      info: {},
+      // 报告文件
+      thrShow: false,
+      fileForm: {},
+    };
+  },
+  async created() {
+    await this.search();
+  },
+  methods: {
+    ...upload(['upload']),
+    ...patentassess(['query', 'update']),
+    ...patentinfo(['fetch']),
+    async search({ skip = 0, limit = this.limit, ...info } = {}) {
+      let res = await this.query({ skip, limit, ...info });
+      if (this.$checkRes(res)) {
+        this.$set(this, `list`, res.data);
+        this.$set(this, `total`, res.total);
+      }
+    },
+    // 审核
+    toExamine(data) {
+      this.$router.push({ path: `/patent/admin/patent/assessment_examine`, query: { id: data.id } });
+    },
+    // 查看专利信息
+    async toView(id) {
+      let res = await this.fetch(id);
+      if (this.$checkRes(res)) {
+        res.data.inventor = JSON.stringify(res.data.inventor.map((i) => i.name));
+        this.$set(this, `info`, res.data);
+        this.show = true;
+      }
+    },
+    // 发送文件
+    toFile(data) {
+      this.$set(this, `fileForm`, data);
+      this.thrShow = true;
+    },
+    // 提交发送
+    async thrSend() {
+      let data = this.fileForm;
+      data.status = '2';
+      let res = await this.update(data);
+      if (this.$checkRes(res)) {
+        this.$toast({ type: `success`, message: `发送文件成功` });
+        this.thrClose();
+      } else {
+        this.$toast({ type: `fail`, message: `${res.errmsg}` });
+      }
+    },
+    // 取消发送
+    thrClose() {
+      this.thrShow = false;
+    },
+    async toUpload({ file }, model) {
+      // 上传,赋值
+      const res = await this.upload({ file, dir: 'assess' });
+      if (this.$checkRes(res)) {
+        this.$set(this.fileForm, model, [{ name: res.name, url: res.uri }]);
+      }
+    },
+    toDelete(file, model) {
+      const index = this.fileForm[model].findIndex((f) => _.isEqual(f, file));
+      this.fileForm[model].splice(index, 1);
+    },
+    // 返回
+    back() {
+      this.$router.push({ path: '/patent/index' });
+    },
+  },
+  computed: {
+    ...mapState(['user']),
+  },
+  metaInfo() {
+    return { title: this.$route.meta.title };
+  },
+  watch: {
+    test: {
+      deep: true,
+      immediate: true,
+      handler(val) {},
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped>
+.dialog {
+  /deep/.van-dialog__content {
+    height: 350px;
+    overflow-y: auto;
+  }
+}
+.thrDialog {
+  .btn {
+    text-align: center;
+    .van-button {
+      margin: 8px;
+    }
+  }
+}
+</style>

+ 99 - 0
src/views/patent/admin/patent/assessment/examine-1.vue

@@ -0,0 +1,99 @@
+<template>
+  <div id="examine-1">
+    <van-row>
+      <van-col span="24" class="main">
+        <van-form @submit="onSubmit">
+          <van-field v-model="form.patent_name" name="patent_name" label="专利名称" center clearable readonly>
+            <!-- <template #button>
+              <van-button size="small" type="info" @click="view(form.patent_id)">专利信息</van-button>
+            </template> -->
+          </van-field>
+          <van-field name="is_money" label="是否缴费">
+            <template #input>
+              <van-radio-group v-model="form.is_money" direction="horizontal" disabled>
+                <van-radio :name="true">已缴费</van-radio>
+                <van-radio :name="false">未缴费</van-radio>
+              </van-radio-group>
+            </template>
+          </van-field>
+          <van-field name="status" label="状态">
+            <template #input>
+              <van-radio-group v-model="form.status" direction="horizontal">
+                <van-radio name="1">通过</van-radio>
+                <van-radio name="-1">拒绝</van-radio>
+              </van-radio-group>
+            </template>
+          </van-field>
+          <van-field
+            v-model="form.remark"
+            name="remark"
+            rows="8"
+            autosize
+            label="审核意见"
+            type="textarea"
+            maxlength="100"
+            placeholder="审核意见"
+            show-word-limit
+            :rules="[{ required: true, message: '审核意见' }]"
+          />
+          <div style="margin: 16px">
+            <van-button round block type="info" native-type="submit">提交审核</van-button>
+          </div>
+        </van-form>
+      </van-col>
+    </van-row>
+  </div>
+</template>
+
+<script>
+import { mapState, createNamespacedHelpers } from 'vuex';
+const { mapActions: upload } = createNamespacedHelpers('upload');
+var moment = require('moment');
+export default {
+  name: 'examine-1',
+  props: {
+    form: { type: Object },
+  },
+  components: {},
+  data: function () {
+    return {};
+  },
+  created() {},
+  methods: {
+    ...upload(['upload']),
+    onSubmit(values) {
+      this.$emit('onSubmit', values);
+    },
+    // 查看专利信息
+    view(patent_id) {
+      this.$emit('view', patent_id);
+    },
+    async toUpload({ file }, model) {
+      // 上传,赋值
+      const res = await this.upload({ file, dir: 'file' });
+      if (this.$checkRes(res)) {
+        this.$set(this.form, model, [{ name: res.name, url: res.uri }]);
+      }
+    },
+    toDelete(file, model) {
+      const index = this.form[model].findIndex((f) => _.isEqual(f, file));
+      this.form[model].splice(index, 1);
+    },
+  },
+  computed: {
+    ...mapState(['user']),
+  },
+  metaInfo() {
+    return { title: this.$route.meta.title };
+  },
+  watch: {
+    test: {
+      deep: true,
+      immediate: true,
+      handler(val) {},
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped></style>

+ 81 - 0
src/views/patent/admin/patent/assessment/info-1.vue

@@ -0,0 +1,81 @@
+<template>
+  <div id="info-1">
+    <van-row>
+      <van-col span="24" class="main">
+        <van-col span="24" class="one">
+          <van-image :src="img_url"></van-image>
+        </van-col>
+        <van-col span="24" class="two">
+          <van-form>
+            <van-field v-model="info.term" name="term" label="专利有效性" readonly />
+            <van-field v-model="info.name" name="name" label="名称" readonly />
+            <van-field v-model="info.create_number" name="create_number" label="申请号" readonly />
+            <van-field v-model="info.create_date" name="create_date" label="申请日" readonly />
+            <van-field v-model="info.success_number" name="success_number" label="公开(公告)号" readonly />
+            <van-field v-model="info.success_date" name="success_date" label="公开(公告)日" readonly />
+            <van-field v-model="info.type" name="type" label="专利类型" readonly />
+            <van-field v-model="info.inventor" name="inventor" label="发明人" readonly />
+            <van-field v-model="info.address" name="address" label="发明人地址" />
+            <van-field v-model="info.apply_personal" name="apply_personal" label="申请人" readonly />
+            <van-field v-model="info.agent_personal" name="agent_personal" label="代理人" readonly />
+            <van-field v-model="info.agent" name="agent" label="代理机构" />
+            <van-field v-model="info.abstract" name="abstract" label="摘要" rows="1" autosize type="textarea" readonly />
+          </van-form>
+        </van-col>
+      </van-col>
+    </van-row>
+  </div>
+</template>
+
+<script>
+import { mapState, createNamespacedHelpers } from 'vuex';
+export default {
+  name: 'info-1',
+  props: {
+    info: { type: Object },
+  },
+  components: {},
+  data: function () {
+    return { img_url: '' };
+  },
+  created() {},
+  methods: {
+    searchImg(data) {
+      if (data && data.length > 0) {
+        var url = data.map((item) => item.url)[0];
+        this.$set(this, `img_url`, url);
+      } else {
+        var url = require('@/assets/fmzl.jpg');
+        this.$set(this, `img_url`, url);
+      }
+    },
+  },
+  computed: {
+    ...mapState(['user']),
+  },
+  metaInfo() {
+    return { title: this.$route.meta.title };
+  },
+  watch: {
+    info: {
+      deep: true,
+      immediate: true,
+      handler(val) {
+        this.searchImg(val.img_url);
+      },
+    },
+  },
+};
+</script>
+<style lang="less" scoped>
+.main {
+  .one {
+    height: 220px;
+    border-bottom: 1px solid #f1f1f1;
+    .van-image {
+      width: 100%;
+      height: 219px;
+    }
+  }
+}
+</style>

+ 115 - 0
src/views/patent/admin/patent/assessment/list-1.vue

@@ -0,0 +1,115 @@
+<template>
+  <div id="list-1">
+    <van-row>
+      <van-col span="24" class="main">
+        <van-col span="24" class="list" v-for="(item, index) in list" :key="index">
+          <van-col span="24" class="title textOver">
+            {{ item.patent_name }}
+          </van-col>
+          <van-col span="24" class="other">
+            <van-col span="24" class="otherInfo">
+              申请时间:<span>{{ getDate(item.meta) }}</span>
+            </van-col>
+            <van-col span="24" class="otherInfo">
+              是否缴费:<span>{{ item.is_money ? '已缴费' : '未缴费' }}</span>
+            </van-col>
+            <van-col span="24" class="otherInfo">
+              申请状态:<span>{{ getStu(item.status) }}</span>
+            </van-col>
+          </van-col>
+          <van-col span="24" class="btn">
+            <van-button size="small" type="info" @click="view(item.patent_id)">查看信息</van-button>
+            <!-- <van-button size="small" type="info">分配专家</van-button> -->
+            <van-button size="small" type="info" @click="examine(item)" v-if="item.status == '0'">审核申请</van-button>
+            <van-button size="small" type="info" @click="toFile(item)" v-if="item.status == '1' || item.status == '2'">报告文件</van-button>
+          </van-col>
+        </van-col>
+      </van-col>
+    </van-row>
+  </div>
+</template>
+
+<script>
+import { mapState, createNamespacedHelpers } from 'vuex';
+var moment = require('moment');
+export default {
+  name: 'list-1',
+  props: {
+    list: { type: Array },
+  },
+  components: {},
+  data: function () {
+    return {};
+  },
+  created() {},
+  methods: {
+    examine(data) {
+      this.$emit('examine', data);
+    },
+    // 查看专利信息
+    view(patent_id) {
+      this.$emit('view', patent_id);
+    },
+    getDate(data) {
+      let newDate = moment(data.createdAt).format('YYYY-MM-DD hh:mm:ss');
+      if (newDate) return newDate;
+    },
+    getStu(status) {
+      if (status == '0') return '待审核';
+      if (status == '1') return '审核通过';
+      if (status == '-1') return '审核拒绝';
+      if (status == '2') return '报告文件已发送';
+    },
+    toFile(data) {
+      this.$emit('toFile', data);
+    },
+  },
+  computed: {
+    ...mapState(['user']),
+  },
+  metaInfo() {
+    return { title: this.$route.meta.title };
+  },
+  watch: {
+    test: {
+      deep: true,
+      immediate: true,
+      handler(val) {},
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped>
+.main {
+  padding: 8px 8px 0 8px;
+  .list {
+    background-color: #fff;
+    margin: 0 0 8px 0;
+    padding: 8px;
+    border-radius: 5px;
+    .title {
+      font-size: 16px;
+      font-weight: bold;
+      margin: 0 0 5px 0;
+    }
+    .other {
+      margin: 0 0 5px 0;
+      .otherInfo {
+        font-size: 14px;
+        color: #666;
+        margin: 0 0 5px 0;
+        span {
+          color: #000;
+        }
+      }
+    }
+    .btn {
+      text-align: center;
+      .van-button {
+        margin: 0 5px;
+      }
+    }
+  }
+}
+</style>

+ 100 - 0
src/views/patent/admin/patent/assessment_examine.vue

@@ -0,0 +1,100 @@
+<template>
+  <div id="assessment_examine">
+    <admin-frame topType="2" @back="back" :rightArrow="false" :usePage="false" :useNav="false">
+      <template v-slot:info>
+        <examine-1 :form="form" @onSubmit="onSubmit" @view="toView"></examine-1>
+      </template>
+    </admin-frame>
+    <van-dialog class="dialog" v-model="show" title="详细信息" :show-confirm-button="false" show-cancel-button>
+      <info-1 :info="info"></info-1>
+    </van-dialog>
+  </div>
+</template>
+
+<script>
+import examine1 from './assessment/examine-1.vue';
+import info1 from './assessment/info-1.vue';
+import adminFrame from '@frame/src/components/mobile-frame/mobile-main.vue';
+import { mapState, createNamespacedHelpers } from 'vuex';
+const { mapActions: patentassess } = createNamespacedHelpers('patentassess');
+const { mapActions: patentinfo } = createNamespacedHelpers('patentinfo');
+export default {
+  name: 'assessment_examine',
+  props: {},
+  components: {
+    adminFrame,
+    examine1,
+    info1,
+  },
+  data: function () {
+    return {
+      form: {},
+      // 专利详细信息
+      show: false,
+      info: {},
+    };
+  },
+  async created() {
+    if (this.id) await this.search();
+  },
+  methods: {
+    ...patentassess(['fetch', 'check']),
+    ...patentinfo({ infoFetch: 'fetch' }),
+    async search() {
+      let res = await this.fetch(this.id);
+      if (this.$checkRes(res)) {
+        this.$set(this, `form`, res.data);
+      }
+    },
+    // 提交审核
+    async onSubmit() {
+      const { id, remark, status, report } = this.form;
+      const obj = { id, status, remark, report };
+      const res = await this.check(obj);
+      if (this.$checkRes(res)) {
+        this.$toast({ type: `success`, message: `审核成功` });
+        this.back();
+      } else {
+        this.$toast({ type: `fail`, message: `${res.errmsg}` });
+      }
+    },
+    // 查看专利信息
+    async toView(id) {
+      let res = await this.infoFetch(id);
+      if (this.$checkRes(res)) {
+        this.$set(this, `info`, res.data);
+        this.show = true;
+      }
+    },
+    // 返回
+    back() {
+      this.$router.push({ path: '/patent/admin/patent/assessment' });
+    },
+  },
+  computed: {
+    ...mapState(['user']),
+    id() {
+      return this.$route.query.id;
+    },
+  },
+  metaInfo() {
+    return { title: this.$route.meta.title };
+  },
+  watch: {
+    test: {
+      deep: true,
+      immediate: true,
+      handler(val) {},
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped>
+.dialog {
+  /deep/.van-dialog__content {
+    height: 350px;
+    overflow-y: auto;
+  }
+}
+</style>

+ 120 - 0
src/views/patent/admin/patent/info.vue

@@ -0,0 +1,120 @@
+<template>
+  <div id="index">
+    <admin-frame @search="search" :limit="limit" :total="total" topType="2" @back="back" @add="add" :useNav="false">
+      <template v-slot:info>
+        <!-- <van-col span="24" class="one">
+          <van-button type="info" size="small" @click="getTemplate">下载导入模板</van-button>
+          <van-button type="info" size="small" @click="toContinue">导入</van-button>
+          <van-button type="info" size="small" @click="exportView">导出</van-button>
+          <van-button type="info" size="small" @click="toResult">导出结果</van-button>
+        </van-col> -->
+        <van-col span="24" class="two">
+          <list-1 :list="list" @detail="detail" @deletes="deletes"></list-1>
+        </van-col>
+      </template>
+    </admin-frame>
+  </div>
+</template>
+
+<script>
+import list1 from './info/list-1.vue';
+import adminFrame from '@frame/src/components/mobile-frame/mobile-main.vue';
+import { mapState, createNamespacedHelpers } from 'vuex';
+const { mapActions: patentinfo } = createNamespacedHelpers('patentinfo');
+
+export default {
+  name: 'index',
+  props: {},
+  components: {
+    adminFrame,
+    list1,
+  },
+  data: function () {
+    return {
+      list: [],
+      limit: 5,
+      total: 0,
+    };
+  },
+  async created() {
+    await this.search();
+  },
+  methods: {
+    ...patentinfo(['query', 'delete', 'toExport']),
+
+    async search({ skip = 0, limit = this.limit, ...info } = {}) {
+      let res = await this.query({ skip, limit, ...info });
+      if (this.$checkRes(res)) {
+        this.$set(this, `list`, res.data);
+        this.$set(this, `total`, res.total);
+      }
+    },
+    add() {
+      this.$router.push({ path: '/patent/admin/patent/info_create' });
+    },
+    // 查看详情
+    detail(data) {
+      this.$router.push({ path: '/patent/admin/patent/info_create', query: { id: data.id } });
+    },
+    // 删除
+    async deletes(data) {
+      let res = await this.delete(data.id);
+      if (this.$checkRes(res)) {
+        this.$toast({ type: `success`, message: `删除成功` });
+        this.search();
+      } else {
+        this.$toast({ type: `fail`, message: `${res.errmsg}` });
+      }
+    },
+    // 返回
+    back() {
+      this.$router.push({ path: '/patent/index' });
+    },
+    // 下载模板
+    getTemplate() {
+      window.location.href = `${process.env.VUE_APP_HOST}/jlstcompany/数据模板.xlsx`;
+      // window.open('./数据模板.xlsx');
+    },
+    // 导入
+    toContinue() {
+      this.$router.push({ path: '/patent/admin/patent/info_import' });
+    },
+    // 导出
+    async exportView() {
+      let res = await this.toExport();
+      if (this.$checkRes(res)) {
+        this.$toast({ type: `success`, message: `导出成功` });
+      } else {
+        this.$toast({ type: `success`, message: `${res.errmsg}` });
+      }
+    },
+    // 导出结果
+    async toResult() {
+      this.$router.push({ path: '/patent/admin/patent/info_result' });
+    },
+  },
+  computed: {
+    ...mapState(['user']),
+  },
+  metaInfo() {
+    return { title: this.$route.meta.title };
+  },
+  watch: {
+    test: {
+      deep: true,
+      immediate: true,
+      handler(val) {},
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped>
+.one {
+  text-align: center;
+  margin: 8px 0;
+  .van-button {
+    margin: 0 5px;
+  }
+}
+</style>

+ 262 - 0
src/views/patent/admin/patent/info/detail-1.vue

@@ -0,0 +1,262 @@
+<template>
+  <div id="detail-1">
+    <van-row>
+      <van-col span="24" class="main">
+        <van-form @submit="onSubmit" label-width="6em">
+          <van-field v-model="form.create_number" name="create_number" label="申请号" :rules="[{ required: true, message: '申请号' }]" />
+          <van-field name="create_date" :value="form.create_date" label="申请日" placeholder="点击选择" @click="selectDate('create_date')" />
+          <van-field v-model="form.success_number" name="success_number" label="公开(公告)号" :rules="[{ required: true, message: '公开(公告)号' }]" />
+          <van-field name="success_date" :value="form.success_date" label="公开(公告)日" placeholder="点击选择" @click="selectDate('success_date')" />
+          <van-field v-model="form.name" name="name" label="标题" :rules="[{ required: true, message: '标题' }]" />
+          <van-field v-model="form.apply_personal" name="apply_personal" label="申请人" :rules="[{ required: true, message: '申请人' }]" />
+          <van-field name="type" label="专利类型" :rules="[{ required: true, message: '专利类型' }]">
+            <template #input>
+              <van-radio-group v-model="form.type" direction="horizontal">
+                <van-radio name="发明">发明</van-radio>
+                <van-radio name="实用新型">实用新型</van-radio>
+                <van-radio name="其他">其他</van-radio>
+              </van-radio-group>
+            </template>
+          </van-field>
+          <van-field name="term" label="专利有效性" :rules="[{ required: true, message: '专利有效性' }]">
+            <template #input>
+              <van-radio-group v-model="form.term" direction="horizontal">
+                <van-radio name="审中">审中</van-radio>
+                <van-radio name="有效">有效</van-radio>
+              </van-radio-group>
+            </template>
+          </van-field>
+          <van-col span="24" class="inventor">
+            <van-col span="24" class="inventor_btn">
+              <van-button size="mini" type="info" @click="selectinventor('inventor')">选择发明人</van-button>
+              <!-- <van-button size="mini" type="info" @click="addinventor('inventor')">添加发明人</van-button> -->
+            </van-col>
+            <van-col span="24" class="inventor_list">
+              <span>发明人:</span>
+              <span v-for="(item, index) in form.inventor" :key="index">
+                {{ index + 1 }}-{{ item.name }}- <span style="color: #ff0000" @click="delInv(item)">删除</span>;
+              </span>
+            </van-col>
+          </van-col>
+          <van-field v-model="form.address" name="address" label="发明人地址" />
+          <van-field v-model="form.agent_personal" name="agent_personal" label="代理人" />
+          <van-field v-model="form.agent" name="agent" label="代理机构" />
+          <van-field v-model="form.abstract" name="abstract" label="摘要" rows="4" autosize type="textarea" />
+          <van-field name="img_url" label="图片">
+            <template #input>
+              <van-uploader
+                :fileList="form.img_url"
+                :max-count="1"
+                :after-read="(file) => toUpload(file, 'img_url')"
+                @delete="(file) => toDelete(file, 'img_url')"
+              />
+            </template>
+          </van-field>
+          <van-field name="status" label="状态" :rules="[{ required: true, message: '状态' }]">
+            <template #input>
+              <van-radio-group v-model="form.status" direction="horizontal">
+                <van-radio name="0">已授权</van-radio>
+                <van-radio name="1">已受理</van-radio>
+              </van-radio-group>
+            </template>
+          </van-field>
+          <!-- 专利信息属性新增201-09-06 -->
+          <van-field v-model="form.nationality" name="nationality" label="公开国别" />
+          <van-field v-model="form.ipc_type" name="ipc_type" label="ipc主分类" />
+          <van-field v-model="form.onlegal_status" name="onlegal_status" label="当前法律状态" />
+          <van-field v-model="form.legal_status" name="legal_status" label="法律状态" />
+          <van-field name="law_date" :value="form.law_date" label="法律文书日期" placeholder="点击选择" @click="selectDate('law_date')" />
+          <van-field v-model="form.on_obligee" name="on_obligee" label="当前权利人" />
+          <van-field v-model="form.apply_address" name="apply_address" label="申请人地址(其他)" />
+          <van-field v-model="form.apply_other" name="apply_other" label="申请人(其他)" />
+          <van-field v-model="form.law_num" name="law_num" label="法律文书编号" />
+          <van-field name="first_opendate" :value="form.first_opendate" label="首次公开日" placeholder="点击选择" @click="selectDate('first_opendate')" />
+          <van-field name="empower_date" :value="form.empower_date" label="授权公告日" placeholder="点击选择" @click="selectDate('empower_date')" />
+          <van-field name="lose_date" :value="form.lose_date" label="失效日" placeholder="点击选择" @click="selectDate('lose_date')" />
+          <van-field name="examine_date" :value="form.examine_date" label="实际审查生效日" placeholder="点击选择" @click="selectDate('examine_date')" />
+          <van-field v-model="form.invention_design" name="invention_design" label="发明人(设计)其他" />
+          <!-- 选择日期公用弹框 -->
+          <van-calendar v-model="calendarShow" @confirm="calendarCon" :min-date="minDate" :max-date="maxDate" />
+          <div style="margin: 16px">
+            <van-button round block type="info" native-type="submit">提交</van-button>
+          </div>
+        </van-form>
+      </van-col>
+    </van-row>
+    <van-dialog class="dialog" v-model="show" title="查询用户" :show-cancel-button="false" :show-confirm-button="false" :closeOnClickOverlay="true">
+      <van-col span="24" class="two">
+        <van-col span="24" class="two_1">
+          <van-search v-model="searchName" show-action placeholder="请输入联系电话" @search="searchUser">
+            <template #action>
+              <div @click="searchUser">搜索</div>
+            </template>
+          </van-search>
+        </van-col>
+        <van-col span="24" class="two_2">
+          <van-col span="24" class="list" v-for="(item, index) in list" :key="index">
+            <van-col span="24" class="name"> {{ item.name }} </van-col>
+            <van-col span="24" class="other">
+              <van-col span="24" class="otherInfo">
+                联系电话:<span>{{ item.phone }}</span>
+              </van-col>
+            </van-col>
+            <van-col span="24" class="btn">
+              <van-button type="info" size="mini" @click="conFirm(item)">确认选择</van-button>
+            </van-col>
+          </van-col>
+          <van-col span="24" class="page">
+            <page @search="searchUser" :limit="limit" :total="total"></page>
+          </van-col>
+        </van-col>
+      </van-col>
+    </van-dialog>
+  </div>
+</template>
+
+<script>
+import { mapState, createNamespacedHelpers } from 'vuex';
+const { mapActions: upload } = createNamespacedHelpers('upload');
+const { mapActions: personal } = createNamespacedHelpers('personal');
+var moment = require('moment');
+export default {
+  name: 'detail-1',
+  props: {
+    form: { type: Object },
+  },
+  components: {},
+  data: function () {
+    return {
+      minDate: new Date(2000, 10, 1),
+      maxDate: new Date(2050, 10, 1),
+      calendarShow: false,
+      calendar_type: '',
+      // 选择发明人&&技术联系人
+      show: false,
+      type: '',
+      // 属于手机号查询用户
+      searchName: '',
+      list: [],
+      limit: 4,
+      total: 0,
+    };
+  },
+  created() {
+    this.searchUser();
+  },
+  methods: {
+    ...upload(['upload']),
+    ...personal({ perQuery: 'query' }),
+    onSubmit(values) {
+      this.$emit('onSubmit', values);
+    },
+    // 打开选择日期弹框
+    selectDate(type) {
+      this.$set(this, `calendar_type`, type);
+      this.calendarShow = true;
+    },
+    // 选中日期
+    calendarCon(date) {
+      this.$set(this.form, this.calendar_type, moment(date).format('YYYY-MM-DD'));
+      this.calendarShow = false;
+    },
+    async toUpload({ file }, model) {
+      // 上传,赋值
+      const res = await this.upload({ file, dir: 'file' });
+      if (this.$checkRes(res)) {
+        this.$set(this.form, model, [{ name: res.name, url: res.uri }]);
+      }
+    },
+    toDelete(file, model) {
+      const index = this.form[model].findIndex((f) => _.isEqual(f, file));
+      this.form[model].splice(index, 1);
+    },
+    // 发明人
+    // 选择发明人&&技术联系人
+    selectinventor(type) {
+      this.$set(this, `type`, type);
+      this.show = true;
+    },
+    // 确认选择
+    conFirm(data) {
+      let user = { user_id: data.id, name: data.name };
+      if (this.type == 'inventor') this.form.inventor.push(user);
+      this.show = false;
+    },
+    // 查询用户
+    async searchUser({ skip = 0, limit = 5, ...info } = {}) {
+      info.code = 'JLKJQYCGD';
+      if (this.searchName) info.phone = this.searchName;
+      let res = await this.perQuery({ skip, limit, ...info });
+      if (this.$checkRes(res)) {
+        this.$set(this, `list`, res.data);
+        this.$set(this, `total`, res.total);
+      }
+    },
+    // 删除发明用户
+    delInv(data) {
+      this.form.inventor.splice(this.form.inventor.indexOf(data), 1);
+    },
+  },
+  computed: {
+    ...mapState(['user']),
+  },
+  metaInfo() {
+    return { title: this.$route.meta.title };
+  },
+  watch: {
+    test: {
+      deep: true,
+      immediate: true,
+      handler(val) {},
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped>
+.dialog {
+  /deep/.van-dialog__content {
+    height: 400px;
+    overflow-y: auto;
+  }
+  .two {
+    .list {
+      border-bottom: 1px dashed #ccc;
+      margin: 0 0 8px 0;
+      padding: 8px;
+      .name {
+        font-size: 16px;
+        margin: 0 0 5px 0;
+      }
+      .other {
+        margin: 0 0 5px 0;
+        .otherInfo {
+          font-size: 14px;
+          color: #666;
+          span {
+            color: #000;
+          }
+        }
+      }
+      .btn {
+        text-align: center;
+      }
+    }
+  }
+}
+/deep/.van-dialog {
+  width: 95%;
+}
+.inventor {
+  padding: 8px 18px;
+  background-color: #fff;
+  .inventor_btn {
+    text-align: center;
+    margin: 0 0 5px 0;
+  }
+  .inventor_list {
+    font-size: 15px;
+    color: #666;
+  }
+}
+</style>

+ 98 - 0
src/views/patent/admin/patent/info/list-1.vue

@@ -0,0 +1,98 @@
+<template>
+  <div id="list-1">
+    <van-row>
+      <van-col span="24" class="main">
+        <van-col span="24" class="list" v-for="(item, index) in list" :key="index">
+          <van-col span="24" class="title textOver">
+            {{ item.name }}
+          </van-col>
+          <van-col span="24" class="other">
+            <van-col span="24" class="otherInfo">
+              专利有效性:<span>{{ item.term || '暂无' }}</span>
+            </van-col>
+            <van-col span="24" class="otherInfo">
+              颁发时间:<span>{{ getDate(item.success_date) }}</span>
+            </van-col>
+          </van-col>
+          <van-col span="24" class="btn">
+            <van-button type="info" size="small" @click="detail(item)">修改信息</van-button>
+            <van-button type="danger" size="small" @click="deletes(item)">删除信息</van-button>
+          </van-col>
+        </van-col>
+      </van-col>
+    </van-row>
+  </div>
+</template>
+
+<script>
+import { mapState, createNamespacedHelpers } from 'vuex';
+const moment = require('moment');
+export default {
+  name: 'list-1',
+  props: { list: { type: Array } },
+  components: {},
+  data: function () {
+    return {};
+  },
+  created() {},
+  methods: {
+    detail(data) {
+      this.$emit('detail', data);
+    },
+    deletes(data) {
+      this.$emit('deletes', data);
+    },
+    // 过滤时间
+    getDate(val) {
+      let newDate = moment(val).format('YYYY-MM-DD');
+      if (newDate) return newDate;
+    },
+  },
+  computed: {
+    ...mapState(['user']),
+  },
+  metaInfo() {
+    return { title: this.$route.meta.title };
+  },
+  watch: {
+    test: {
+      deep: true,
+      immediate: true,
+      handler(val) {},
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped>
+.main {
+  margin: 8px 0 0 0;
+  .list {
+    background-color: #fff;
+    margin: 0 0 10px 0;
+    box-shadow: 0 0 5px #f1f1f1;
+    padding: 8px;
+    .title {
+      font-size: 16px;
+      font-weight: bold;
+      margin: 0 0 5px 0;
+    }
+    .other {
+      .otherInfo {
+        font-size: 14px;
+        color: #666;
+        margin: 0 0 5px 0;
+        span {
+          color: #000;
+        }
+      }
+    }
+    .btn {
+      text-align: center;
+      .van-button {
+        margin: 0 10px;
+      }
+    }
+  }
+}
+</style>

+ 108 - 0
src/views/patent/admin/patent/info/result-1.vue

@@ -0,0 +1,108 @@
+<template>
+  <div id="list-1">
+    <van-row>
+      <van-col span="24" class="main">
+        <van-col span="24" class="list" v-for="(item, index) in list" :key="index">
+          <van-col span="24" class="title textOver">
+            {{ item.name }}
+          </van-col>
+          <van-col span="24" class="other">
+            <van-col span="24" class="otherInfo">
+              导出数据时间:<span>{{ getDate(item.meta.createdAt) }}</span>
+            </van-col>
+            <van-col span="24" class="otherInfo">
+              状态:<span>{{ getStu(item.status) }}</span>
+            </van-col>
+            <van-col span="24" class="otherInfo">
+              进度:<span>{{ item.progress || '暂无' }}%</span>
+            </van-col>
+          </van-col>
+          <van-col span="24" class="btn">
+            <van-button type="info" size="small" @click="download(item)">下载</van-button>
+          </van-col>
+        </van-col>
+      </van-col>
+    </van-row>
+  </div>
+</template>
+
+<script>
+import { mapState, createNamespacedHelpers } from 'vuex';
+const moment = require('moment');
+export default {
+  name: 'list-1',
+  props: { list: { type: Array } },
+  components: {},
+  data: function () {
+    return {};
+  },
+  created() {},
+  methods: {
+    download(data) {
+      this.$emit('download', data);
+    },
+    deletes(data) {
+      this.$emit('deletes', data);
+    },
+    // 过滤时间
+    getDate(val) {
+      let newDate = moment(val).format('YYYY-MM-DD hh:mm');
+      if (newDate) return newDate;
+    },
+    // 整理状态
+    getStu(data) {
+      if (data == '0') return '未开始';
+      else if (data == '1') return '进行中';
+      else if (data == '2') return '导出成功';
+      else if (data == '3') return '导出失败';
+      else return '未知状态';
+    },
+  },
+  computed: {
+    ...mapState(['user']),
+  },
+  metaInfo() {
+    return { title: this.$route.meta.title };
+  },
+  watch: {
+    test: {
+      deep: true,
+      immediate: true,
+      handler(val) {},
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped>
+.main {
+  margin: 8px 0 0 0;
+  .list {
+    background-color: #fff;
+    margin: 0 0 10px 0;
+    box-shadow: 0 0 5px #f1f1f1;
+    padding: 8px;
+    .title {
+      font-size: 16px;
+      font-weight: bold;
+      margin: 0 0 5px 0;
+    }
+    .other {
+      .otherInfo {
+        font-size: 14px;
+        color: #666;
+        margin: 0 0 5px 0;
+        span {
+          color: #000;
+        }
+      }
+    }
+    .btn {
+      text-align: center;
+      .van-button {
+        margin: 0 10px;
+      }
+    }
+  }
+}
+</style>

+ 84 - 0
src/views/patent/admin/patent/info_create.vue

@@ -0,0 +1,84 @@
+<template>
+  <div id="info_create">
+    <admin-frame topType="2" @back="back" :rightArrow="false" :usePage="false" :useNav="false">
+      <template v-slot:info>
+        <detail-1 :form="form" @onSubmit="onSubmit"></detail-1>
+      </template>
+    </admin-frame>
+  </div>
+</template>
+
+<script>
+import detail1 from './info/detail-1.vue';
+import adminFrame from '@frame/src/components/mobile-frame/mobile-main.vue';
+import { mapState, createNamespacedHelpers } from 'vuex';
+const { mapActions: patentinfo } = createNamespacedHelpers('patentinfo');
+export default {
+  name: 'info_create',
+  props: {},
+  components: {
+    adminFrame,
+    detail1,
+  },
+  data: function () {
+    return {
+      form: { inventor: [] },
+    };
+  },
+  async created() {
+    if (this.id) await this.search();
+  },
+  methods: {
+    ...patentinfo(['fetch', 'create', 'update']),
+    async search() {
+      let res = await this.fetch(this.id);
+      if (this.$checkRes(res)) {
+        this.$set(this, `form`, res.data);
+      }
+    },
+    async onSubmit() {
+      let data = this.form;
+      if (data.id) {
+        let res = await this.update(data);
+        if (this.$checkRes(res)) {
+          this.$toast({ type: `success`, message: `修改成功` });
+          this.back();
+        } else {
+          this.$toast({ type: `fail`, message: `${res.errmsg}` });
+        }
+      } else {
+        data.trans_status = '0';
+        let res = await this.create(data);
+        if (this.$checkRes(res)) {
+          this.$toast({ type: `success`, message: `添加成功` });
+          this.back();
+        } else {
+          this.$toast({ type: `fail`, message: `${res.errmsg}` });
+        }
+      }
+    },
+    // 返回
+    back() {
+      this.$router.push({ path: '/patent/admin/patent/info' });
+    },
+  },
+  computed: {
+    ...mapState(['user']),
+    id() {
+      return this.$route.query.id;
+    },
+  },
+  metaInfo() {
+    return { title: this.$route.meta.title };
+  },
+  watch: {
+    test: {
+      deep: true,
+      immediate: true,
+      handler(val) {},
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped></style>

+ 126 - 0
src/views/patent/admin/patent/info_import.vue

@@ -0,0 +1,126 @@
+<template>
+  <div id="index">
+    <admin-frame topType="2" @back="back" :usePage="false" :rightArrow="false" :useNav="false">
+      <template v-slot:info>
+        <van-form @submit="onSubmit">
+          <van-field readonly clickable name="mechanism_name" :value="form.mechanism_name" label="选择机构" placeholder="点击选择" @click="showPicker = true" />
+          <van-popup v-model="showPicker" position="bottom">
+            <van-picker show-toolbar :columns="mechanismList" value-key="deptname" @confirm="mechanismCon" @cancel="showPicker = false" />
+          </van-popup>
+          <van-field v-model="form.origin" name="origin" label="数据来源" placeholder="数据来源" />
+          <van-field name="uri" label="文件">
+            <template #input>
+              <van-uploader
+                :fileList="form.uri"
+                :max-count="1"
+                :after-read="(file) => toUpload(file, 'uri')"
+                @delete="(file) => toDelete(file, 'uri')"
+                accept="file"
+              />
+            </template>
+          </van-field>
+          <div style="margin: 16px; text-align: center">
+            <van-button :loading="loading" type="info" native-type="submit" loading-text="加载中...">确认导入</van-button>
+          </div>
+        </van-form>
+      </template>
+    </admin-frame>
+  </div>
+</template>
+
+<script>
+import adminFrame from '@frame/src/components/mobile-frame/mobile-main.vue';
+import { mapState, createNamespacedHelpers } from 'vuex';
+const { mapActions: patentinfo } = createNamespacedHelpers('patentinfo');
+const { mapActions: adminLogin } = createNamespacedHelpers('adminLogin');
+const { mapActions: personal } = createNamespacedHelpers('personal');
+const { mapActions: upload } = createNamespacedHelpers('upload');
+export default {
+  name: 'index',
+  props: {},
+  components: {
+    adminFrame,
+  },
+  data: function () {
+    return {
+      form: {},
+      // 机构列表
+      mechanismList: [],
+      showPicker: false,
+      loading: false,
+    };
+  },
+  created() {
+    this.searchOther();
+  },
+  methods: {
+    ...upload(['upload']),
+    ...adminLogin(['query']),
+    ...personal({ perQuery: 'query' }),
+    ...patentinfo(['toImport']),
+    // 提交导入
+    async onSubmit(values) {
+      let data = values;
+      data.uri = data.uri ? data.uri[0].uri : '';
+      this.loading = true;
+      let res = await this.toImport(data);
+      if (this.$checkRes(res)) {
+        this.$toast({ type: `success`, message: `导入成功` });
+        this.loading = false;
+      } else {
+        this.$toast({ type: `success`, message: `${res.errmsg}` });
+      }
+    },
+    // 选择机构,查询用户
+    async mechanismCon(values) {
+      this.$set(this.form, `mechanism_name`, values.deptname);
+      this.showPicker = false;
+    },
+    // 返回
+    back() {
+      this.$router.push({ path: '/patent/admin/patent/info' });
+    },
+    // 查询机构
+    async searchOther() {
+      let res = await this.query({ pid: this.user._id });
+      if (this.$checkRes(res)) {
+        this.$set(this, `mechanismList`, res.data);
+      }
+    },
+    async toUpload({ file }, model) {
+      // 上传,赋值
+      const res = await this.upload({ file, dir: 'patent' });
+      if (this.$checkRes(res)) {
+        this.$set(this.form, model, [{ name: res.name, uri: res.uri }]);
+      }
+    },
+    toDelete(file, model) {
+      const index = this.form[model].findIndex((f) => _.isEqual(f, file));
+      this.form[model].splice(index, 1);
+    },
+  },
+  computed: {
+    ...mapState(['user']),
+  },
+  metaInfo() {
+    return { title: this.$route.meta.title };
+  },
+  watch: {
+    test: {
+      deep: true,
+      immediate: true,
+      handler(val) {},
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped>
+.one {
+  text-align: center;
+  margin: 8px 0;
+  .van-button {
+    margin: 0 5px;
+  }
+}
+</style>

+ 67 - 0
src/views/patent/admin/patent/info_result.vue

@@ -0,0 +1,67 @@
+<template>
+  <div id="info_result">
+    <admin-frame @search="search" :limit="limit" :total="total" topType="2" @back="back" :rightArrow="false" :useNav="false">
+      <template v-slot:info>
+        <result-1 :list="list" @download="download"></result-1>
+      </template>
+    </admin-frame>
+  </div>
+</template>
+
+<script>
+import result1 from './info/result-1.vue';
+import adminFrame from '@frame/src/components/mobile-frame/mobile-main.vue';
+import { mapState, createNamespacedHelpers } from 'vuex';
+const { mapActions: mission } = createNamespacedHelpers('mission');
+export default {
+  name: 'info_result',
+  props: {},
+  components: {
+    adminFrame,
+    result1,
+  },
+  data: function () {
+    return {
+      list: [],
+      limit: 5,
+      total: 0,
+    };
+  },
+  created() {
+    this.search();
+  },
+  methods: {
+    ...mission(['query']),
+    async search({ skip = 0, limit = this.limit, ...info } = {}) {
+      const res = await this.query({ skip, limit });
+      if (this.$checkRes(res)) {
+        this.$set(this, 'list', res.data);
+        this.$set(this, 'total', res.total);
+      }
+    },
+    // 下载导出文件
+    download(data) {
+      window.location.href = `${process.env.VUE_APP_HOST}/${data.uri}`;
+    },
+    // 返回
+    back() {
+      this.$router.push({ path: '/patent/admin/patent/info' });
+    },
+  },
+  computed: {
+    ...mapState(['user']),
+  },
+  metaInfo() {
+    return { title: this.$route.meta.title };
+  },
+  watch: {
+    test: {
+      deep: true,
+      immediate: true,
+      handler(val) {},
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped></style>

+ 67 - 0
src/views/patent/admin/patent/trans.vue

@@ -0,0 +1,67 @@
+<template>
+  <div id="index">
+    <admin-frame @search="search" :limit="limit" :total="total" topType="2" :rightArrow="false" @back="back" :useNav="false">
+      <template v-slot:info>
+        <list-1 :list="list" @detail="detail"></list-1>
+      </template>
+    </admin-frame>
+  </div>
+</template>
+
+<script>
+import list1 from './trans/list-1.vue';
+import adminFrame from '@frame/src/components/mobile-frame/mobile-main.vue';
+import { mapState, createNamespacedHelpers } from 'vuex';
+const { mapActions: patenttrans } = createNamespacedHelpers('patenttrans');
+export default {
+  name: 'index',
+  props: {},
+  components: {
+    adminFrame,
+    list1,
+  },
+  data: function () {
+    return {
+      list: [],
+      limit: 5,
+      total: 0,
+    };
+  },
+  async created() {
+    await this.search();
+  },
+  methods: {
+    ...patenttrans(['query']),
+    async search({ skip = 0, limit = this.limit, ...info } = {}) {
+      let res = await this.query({ skip, limit, ...info });
+      if (this.$checkRes(res)) {
+        this.$set(this, `list`, res.data);
+        this.$set(this, `total`, res.total);
+      }
+    },
+    // 查看详情
+    detail(data) {
+      this.$router.push({ path: '/patent/admin/patent/trans_info', query: { id: data.id } });
+    },
+    // 返回
+    back() {
+      this.$router.push({ path: '/patent/index' });
+    },
+  },
+  computed: {
+    ...mapState(['user']),
+  },
+  metaInfo() {
+    return { title: this.$route.meta.title };
+  },
+  watch: {
+    test: {
+      deep: true,
+      immediate: true,
+      handler(val) {},
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped></style>

+ 76 - 0
src/views/patent/admin/patent/trans/info-1.vue

@@ -0,0 +1,76 @@
+<template>
+  <div id="info-1">
+    <van-row>
+      <van-col span="24" class="main">
+        <van-col span="24" class="one">
+          <van-form label-width="5em">
+            <van-field v-model="form.create_number" name="create_number" label="申请号" readonly />
+            <van-field v-model="form.patent_name" name="patent_name" label="专利名称" readonly />
+            <van-field v-model="form.contact" name="contact" label="联系人" readonly />
+            <van-field v-model="form.phone" name="phone" label="联系电话" readonly />
+            <van-field v-model="form.email" name="email" label="电子邮箱" readonly />
+            <van-field v-model="form.budget" name="budget" type="digit" label="投资预算" readonly />
+            <van-field v-model="form.type" name="type" label="交易类型" readonly />
+            <van-field name="is_report" label="评估报告">
+              <template #input>
+                <van-radio-group v-model="form.is_report" direction="horizontal" disabled>
+                  <van-radio :name="true">有</van-radio>
+                  <van-radio :name="false">无</van-radio>
+                </van-radio-group>
+                <van-button type="info" size="small" v-if="form.is_report == true" @click="download(form.report)">下载报告</van-button>
+              </template>
+            </van-field>
+            <van-field v-model="form.requirementdesc" name="requirementdesc" label="技术说明" rows="2" autosize type="textarea" readonly />
+            <van-field v-model="form.expect" name="expect" label="商业预期" rows="2" autosize type="textarea" readonly />
+            <van-field v-model="form.condition" name="condition" label="条件及要求" rows="2" autosize type="textarea" readonly />
+          </van-form>
+        </van-col>
+      </van-col>
+    </van-row>
+  </div>
+</template>
+
+<script>
+import { mapState, createNamespacedHelpers } from 'vuex';
+export default {
+  name: 'info-1',
+  props: {
+    form: { type: Object },
+  },
+  components: {},
+  data: function () {
+    return {};
+  },
+  created() {},
+  methods: {
+    download(data) {
+      window.location.href = `${process.env.VUE_APP_HOST}/${data[0].url}`;
+    },
+  },
+  computed: {
+    ...mapState(['user']),
+  },
+  metaInfo() {
+    return { title: this.$route.meta.title };
+  },
+  watch: {
+    test: {
+      deep: true,
+      immediate: true,
+      handler(val) {},
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped>
+.main {
+  .two {
+    text-align: center;
+    margin: 10px 0;
+    .van-button {
+      margin: 0 10px;
+    }
+  }
+}
+</style>

+ 85 - 0
src/views/patent/admin/patent/trans/list-1.vue

@@ -0,0 +1,85 @@
+<template>
+  <div id="list-3">
+    <van-row>
+      <van-col span="24" class="main">
+        <van-col span="24" class="list" v-for="(item, index) in list" :key="index" @click.native="detail(item)">
+          <van-col span="24" class="title textOver">
+            {{ item.patent_name }}
+          </van-col>
+          <van-col span="24" class="other">
+            <van-col span="24" class="otherInfo">
+              申请号:<span>{{ item.create_number || '暂无' }}</span>
+            </van-col>
+            <van-col span="24" class="otherInfo">
+              交易类型:<span>{{ item.type || '暂无' }}</span>
+            </van-col>
+            <van-col span="24" class="otherInfo">
+              投资预算:<span>{{ item.budget || '暂无' }}万元</span>
+            </van-col>
+          </van-col>
+        </van-col>
+      </van-col>
+    </van-row>
+  </div>
+</template>
+
+<script>
+import { mapState, createNamespacedHelpers } from 'vuex';
+export default {
+  name: 'list-3',
+  props: {
+    list: { type: Array },
+  },
+  components: {},
+  data: function () {
+    return {};
+  },
+  created() {},
+  methods: {
+    detail(data) {
+      this.$emit('detail', data);
+    },
+  },
+  computed: {
+    ...mapState(['user']),
+  },
+  metaInfo() {
+    return { title: this.$route.meta.title };
+  },
+  watch: {
+    test: {
+      deep: true,
+      immediate: true,
+      handler(val) {},
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped>
+.main {
+  padding: 8px 8px 0 8px;
+  .list {
+    background-color: #fff;
+    margin: 0 0 8px 0;
+    padding: 8px;
+    border-radius: 5px;
+    .title {
+      font-size: 16px;
+      font-weight: bold;
+      margin: 0 0 5px 0;
+    }
+    .other {
+      margin: 0 0 5px 0;
+      .otherInfo {
+        font-size: 14px;
+        color: #666;
+        margin: 0 0 5px 0;
+        span {
+          color: #000;
+        }
+      }
+    }
+  }
+}
+</style>

+ 63 - 0
src/views/patent/admin/patent/trans_info.vue

@@ -0,0 +1,63 @@
+<template>
+  <div id="trans_info">
+    <admin-frame topType="2" @back="back" :rightArrow="false" :usePage="false" :useNav="false">
+      <template v-slot:info>
+        <info-1 :form="form"></info-1>
+      </template>
+    </admin-frame>
+  </div>
+</template>
+
+<script>
+import info1 from './trans/info-1.vue';
+import adminFrame from '@frame/src/components/mobile-frame/mobile-main.vue';
+import { mapState, createNamespacedHelpers } from 'vuex';
+const { mapActions: patenttrans } = createNamespacedHelpers('patenttrans');
+export default {
+  name: 'trans_info',
+  props: {},
+  components: {
+    adminFrame,
+    info1,
+  },
+  data: function () {
+    return {
+      form: {},
+    };
+  },
+  async created() {
+    await this.search();
+  },
+  methods: {
+    ...patenttrans(['fetch']),
+    async search() {
+      let res = await this.fetch(this.id);
+      if (this.$checkRes(res)) {
+        this.$set(this, `form`, res.data);
+      }
+    },
+    // 返回
+    back() {
+      this.$router.push({ path: '/patent/admin/patent/trans' });
+    },
+  },
+  computed: {
+    ...mapState(['user']),
+    id() {
+      return this.$route.query.id;
+    },
+  },
+  metaInfo() {
+    return { title: this.$route.meta.title };
+  },
+  watch: {
+    test: {
+      deep: true,
+      immediate: true,
+      handler(val) {},
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped></style>