guhongwei 3 tahun lalu
induk
melakukan
66bb292588
48 mengubah file dengan 4684 tambahan dan 10 penghapusan
  1. 138 0
      src/router/index.js
  2. 3 3
      src/views/patent/market/index.vue
  3. 1 1
      src/views/patent/parts/patent-1.vue
  4. 1 1
      src/views/patent/parts/trans-1.vue
  5. 97 0
      src/views/patent/user/apply/analysis/detail.vue
  6. 72 0
      src/views/patent/user/apply/analysis/index.vue
  7. 171 0
      src/views/patent/user/apply/analysis/parts/detail-2.vue
  8. 110 0
      src/views/patent/user/apply/analysis/parts/list-2.vue
  9. 90 0
      src/views/patent/user/apply/analysis/parts/result-2.vue
  10. 69 0
      src/views/patent/user/apply/analysis/result.vue
  11. 103 0
      src/views/patent/user/apply/apply/detail.vue
  12. 71 0
      src/views/patent/user/apply/apply/gzjDetail.vue
  13. 76 0
      src/views/patent/user/apply/apply/index.vue
  14. 407 0
      src/views/patent/user/apply/apply/parts/detail-1.vue
  15. 110 0
      src/views/patent/user/apply/apply/parts/list-1.vue
  16. 139 0
      src/views/patent/user/apply/apply/parts/list-2.vue
  17. 107 0
      src/views/patent/user/apply/apply/parts/result-1.vue
  18. 68 0
      src/views/patent/user/apply/apply/result.vue
  19. 102 0
      src/views/patent/user/apply/assessment/detail.vue
  20. 98 0
      src/views/patent/user/apply/assessment/index.vue
  21. 176 0
      src/views/patent/user/apply/assessment/parts/detail-3.vue
  22. 81 0
      src/views/patent/user/apply/assessment/parts/info-1.vue
  23. 110 0
      src/views/patent/user/apply/assessment/parts/list-3.vue
  24. 101 0
      src/views/patent/user/apply/assessment/parts/result-3.vue
  25. 92 0
      src/views/patent/user/apply/assessment/result.vue
  26. 48 0
      src/views/patent/user/chat/index.vue
  27. 64 0
      src/views/patent/user/message/notice.vue
  28. 95 0
      src/views/patent/user/message/parts/list-1.vue
  29. 92 0
      src/views/patent/user/message/parts/list-2.vue
  30. 90 0
      src/views/patent/user/message/parts/list-3.vue
  31. 66 0
      src/views/patent/user/message/read.vue
  32. 74 0
      src/views/patent/user/message/unRead.vue
  33. 65 0
      src/views/patent/user/patent/early/index.vue
  34. 88 0
      src/views/patent/user/patent/information/detail.vue
  35. 124 0
      src/views/patent/user/patent/information/index.vue
  36. 90 0
      src/views/patent/user/patent/information/parts/detail-1.vue
  37. 98 0
      src/views/patent/user/patent/information/parts/list-1.vue
  38. 100 0
      src/views/patent/user/patent/information/parts/trans-1.vue
  39. 111 0
      src/views/patent/user/patent/information/trans_create.vue
  40. 53 0
      src/views/patent/user/patent/navigation/index.vue
  41. 83 0
      src/views/patent/user/patent/parts/list-4.vue
  42. 102 0
      src/views/patent/user/transaction/contract.vue
  43. 75 0
      src/views/patent/user/transaction/index.vue
  44. 173 0
      src/views/patent/user/transaction/info.vue
  45. 186 0
      src/views/patent/user/transaction/parts/form-1.vue
  46. 112 0
      src/views/patent/user/transaction/parts/info-1.vue
  47. 98 0
      src/views/patent/user/transaction/parts/list-1.vue
  48. 4 5
      src/views/patent/user/userBtn.vue

+ 138 - 0
src/router/index.js

@@ -107,6 +107,144 @@ const patent = [
     meta: { title: '专利管理中心' },
     component: () => import('../views/patent/index.vue'),
   },
+  // 专利超市
+  {
+    path: '/patent/market/index',
+    meta: { title: '专利超市' },
+    component: () => import('../views/patent/market/index.vue'),
+  },
+  {
+    path: '/patent/market/detail',
+    meta: { title: '专利超市-详细信息' },
+    component: () => import('../views/patent/market/detail.vue'),
+  },
+  {
+    path: '/patent/market/transDetail',
+    meta: { title: '专利超市-详细信息' },
+    component: () => import('../views/patent/market/transDetail.vue'),
+  },
+  // 资讯服务
+  {
+    path: '/patent/user/chat/index',
+    meta: { title: '咨詢服务' },
+    component: () => import('../views/patent/user/chat/index.vue'),
+  },
+  // 专利运营-个人用户
+  // 我的消息
+  {
+    path: '/patent/user/message/unRead',
+    meta: { title: '未读信息查看' },
+    component: () => import('../views/patent/user/message/unRead.vue'),
+  },
+  {
+    path: '/patent/user/message/read',
+    meta: { title: '已读信息查看' },
+    component: () => import('../views/patent/user/message/read.vue'),
+  },
+  {
+    path: '/patent/user/message/notice',
+    meta: { title: '通知查看' },
+    component: () => import('../views/patent/user/message/notice.vue'),
+  },
+  // 我的申请
+  // 专利申请
+  {
+    path: '/patent/user/apply/apply',
+    meta: { title: '专利申请' },
+    component: () => import('../views/patent/user/apply/apply/index.vue'),
+  },
+  {
+    path: '/patent/user/apply/apply/detail',
+    meta: { title: '专利申请-审批单' },
+    component: () => import('../views/patent/user/apply/apply/detail.vue'),
+  },
+  {
+    path: '/patent/user/apply/apply/result',
+    meta: { title: '专利申请-审核结果' },
+    component: () => import('../views/patent/user/apply/apply/result.vue'),
+  },
+  {
+    path: '/patent/user/apply/apply/gzjDetail',
+    meta: { title: '专利申请-国知局信息' },
+    component: () => import('../views/patent/user/apply/apply/gzjDetail.vue'),
+  },
+  // 查新检索
+  {
+    path: '/patent/user/apply/analysis',
+    meta: { title: '查新检索' },
+    component: () => import('../views/patent/user/apply/analysis/index.vue'),
+  },
+  {
+    path: '/patent/user/apply/analysis/detail',
+    meta: { title: '查新检索-交底书' },
+    component: () => import('../views/patent/user/apply/analysis/detail.vue'),
+  },
+  {
+    path: '/patent/user/apply/analysis/result',
+    meta: { title: '查新检索-审核结果' },
+    component: () => import('../views/patent/user/apply/analysis/result.vue'),
+  },
+  //价值评估
+  {
+    path: '/patent/user/apply/assessment',
+    meta: { title: '价值评估' },
+    component: () => import('../views/patent/user/apply/assessment/index.vue'),
+  },
+  {
+    path: '/patent/user/apply/assessment/detail',
+    meta: { title: '价值评估-申请评估' },
+    component: () => import('../views/patent/user/apply/assessment/detail.vue'),
+  },
+  {
+    path: '/patent/user/apply/assessment/result',
+    meta: { title: '价值评估-审核结果' },
+    component: () => import('../views/patent/user/apply/assessment/result.vue'),
+  },
+  // 我的专利
+  // 专利信息
+  {
+    path: '/patent/user/patent/information',
+    meta: { title: '专利信息' },
+    component: () => import('../views/patent/user/patent/information/index.vue'),
+  },
+  {
+    path: '/patent/user/patent/information/detail',
+    meta: { title: '专利信息-详细信息' },
+    component: () => import('../views/patent/user/patent/information/detail.vue'),
+  },
+  {
+    path: '/patent/user/patent/information/trans_create',
+    meta: { title: '专利信息-发起交易' },
+    component: () => import('../views/patent/user/patent/information/trans_create.vue'),
+  },
+  // 专利导航
+  {
+    path: '/patent/user/patent/navigation',
+    meta: { title: '专利导航' },
+    component: () => import('../views/patent/user/patent/navigation/index.vue'),
+  },
+  // 专利预警
+  {
+    path: '/patent/user/patent/early',
+    meta: { title: '专利预警' },
+    component: () => import('../views/patent/user/patent/early/index.vue'),
+  },
+  // 我的交易
+  {
+    path: '/patent/user/transaction/index',
+    meta: { title: '专利交易' },
+    component: () => import('../views/patent/user/transaction/index.vue'),
+  },
+  {
+    path: '/patent/user/transaction/info',
+    meta: { title: '专利交易-详细信息' },
+    component: () => import('../views/patent/user/transaction/info.vue'),
+  },
+  {
+    path: '/patent/user/transaction/contract',
+    meta: { title: '专利交易-填写合同' },
+    component: () => import('../views/patent/user/transaction/contract.vue'),
+  },
 ];
 const web = [
   {

+ 3 - 3
src/views/patent/market/index.vue

@@ -74,11 +74,11 @@ export default {
     },
     // 专利详情
     detail(data) {
-      this.$router.push({ path: '/service/patent/market/detail', query: { id: data._id } });
+      this.$router.push({ path: '/patent/market/detail', query: { id: data._id } });
     },
     // 交易详情
     twoDetail(data) {
-      this.$router.push({ path: '/service/patent/market/transDetail', query: { id: data._id } });
+      this.$router.push({ path: '/patent/market/transDetail', query: { id: data._id } });
     },
     change(name) {
       this.$set(this, `active`, name);
@@ -86,7 +86,7 @@ export default {
     },
     // 返回
     back() {
-      this.$router.push({ path: '/service/patent/index' });
+      this.$router.push({ path: '/patent/index' });
     },
   },
   computed: {

+ 1 - 1
src/views/patent/parts/patent-1.vue

@@ -36,7 +36,7 @@ export default {
     },
     // 查看详情
     detail(data) {
-      this.$router.push({ path: '/service/patent/market/detail', query: { id: data._id } });
+      this.$router.push({ path: '/patent/market/detail', query: { id: data._id } });
     },
   },
   computed: {

+ 1 - 1
src/views/patent/parts/trans-1.vue

@@ -36,7 +36,7 @@ export default {
       }
     },
     detail(data) {
-      this.$router.push({ path: '/service/patent/market/transDetail', query: { id: data._id } });
+      this.$router.push({ path: '/patent/market/transDetail', query: { id: data._id } });
     },
   },
   computed: {

+ 97 - 0
src/views/patent/user/apply/analysis/detail.vue

@@ -0,0 +1,97 @@
+<template>
+  <div id="detail">
+    <admin-frame topType="2" @back="back" :rightArrow="false" :usePage="false" :useNav="false">
+      <template v-slot:info>
+        <detail-2 :form="form" @onSubmit="onSubmit"></detail-2>
+      </template>
+    </admin-frame>
+  </div>
+</template>
+
+<script>
+import detail2 from './parts/detail-2.vue';
+import adminFrame from '@frame/src/components/mobile-frame/mobile-main.vue';
+import { mapState, createNamespacedHelpers } from 'vuex';
+const { mapActions: patentanalysis } = createNamespacedHelpers('patentanalysis');
+export default {
+  name: 'detail',
+  props: {},
+  components: {
+    adminFrame,
+    detail2,
+  },
+  data: function () {
+    return {
+      form: {
+        questions: {},
+      },
+    };
+  },
+  async created() {
+    await this.search();
+  },
+  methods: {
+    ...patentanalysis(['fetch', 'create', 'update']),
+    async search() {
+      if (this.id) {
+        let res = await this.fetch(this.id);
+        if (this.$checkRes(res)) {
+          if (!res.data.questions) res.data.questions = {};
+          this.$set(this, `form`, res.data);
+        }
+      } else {
+        let data = this.form;
+        data.user_id = this.user._id;
+        data.apply_name = this.user.name;
+        data.status = '0';
+        data.inventor = this.user.name;
+        data.contact = this.user.name;
+        data.questions = {};
+        this.$set(this, `form`, data);
+      }
+    },
+    async onSubmit({ data }) {
+      if (data._id) {
+        data.status = '0';
+        let res = await this.update(data);
+        if (this.$checkRes(res)) {
+          this.$toast({ type: `success`, message: `修改查新检索申请成功` });
+          this.back();
+        } else {
+          this.$toast({ type: `success`, message: `${res.errmsg}` });
+        }
+      } else {
+        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/user/apply/analysis' });
+    },
+  },
+  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>

+ 72 - 0
src/views/patent/user/apply/analysis/index.vue

@@ -0,0 +1,72 @@
+<template>
+  <div id="index">
+    <admin-frame @search="search" :limit="limit" :total="total" topType="2" @back="back" @add="add" :useNav="false">
+      <template v-slot:info>
+        <list-2 :list="list" @result="result"></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: patentanalysis } = createNamespacedHelpers('patentanalysis');
+export default {
+  name: 'index',
+  props: {},
+  components: {
+    adminFrame,
+    list2,
+  },
+  data: function () {
+    return {
+      list: [],
+      limit: 5,
+      total: 0,
+    };
+  },
+  async created() {
+    await this.search();
+  },
+  methods: {
+    ...patentanalysis(['query']),
+    async search({ skip = 0, limit = this.limit, ...info } = {}) {
+      info.user_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);
+      }
+    },
+    // 添加
+    add() {
+      this.$router.push({ path: '/patent/user/apply/analysis/detail' });
+    },
+    // 查看结果
+    result(data) {
+      this.$router.push({ path: '/patent/user/apply/analysis/result', 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>

+ 171 - 0
src/views/patent/user/apply/analysis/parts/detail-2.vue

@@ -0,0 +1,171 @@
+<template>
+  <div id="detail-2">
+    <van-row>
+      <van-col span="24" class="main">
+        <van-form @submit="onSubmit">
+          <van-field v-model="form.name" name="发明名称" label="发明名称" placeholder="发明名称" :rules="[{ required: false, message: '发明名称' }]" />
+          <van-field v-model="form.apply_name" name="申请人" label="申请人" placeholder="申请人" :rules="[{ required: false, message: '申请人' }]" />
+          <van-field readonly clickable name="type" :value="form.type" label="选择类型" placeholder="点击选择" @click="typePicker = true" />
+          <van-popup v-model="typePicker" position="bottom">
+            <van-picker show-toolbar :columns="typeList" @confirm="typeCon" @cancel="typePicker = false" />
+          </van-popup>
+          <van-field v-model="form.inventor" name="发明人" label="发明人" placeholder="发明人" :rules="[{ required: false, message: '发明人' }]" />
+          <van-field
+            v-model="form.contact"
+            name="技术联系人"
+            label="技术联系人"
+            placeholder="技术联系人"
+            :rules="[{ required: false, message: '技术联系人' }]"
+          />
+          <van-field v-model="form.phone" name="联系人电话" label="联系人电话" placeholder="联系人电话" :rules="[{ required: false, message: '联系人电话' }]" />
+          <van-field v-model="form.email" name="联系人邮箱" label="联系人邮箱" placeholder="联系人邮箱" :rules="[{ required: false, message: '联系人邮箱' }]" />
+          <van-field
+            v-model="form.questions.q8"
+            type="textarea"
+            rows="1"
+            autosize
+            name="特殊情况说明"
+            label="特殊情况说明"
+            placeholder="特殊情况说明"
+            :rules="[{ required: false, message: '特殊情况说明' }]"
+          />
+          <van-field
+            v-model="form.questions.q1"
+            type="textarea"
+            rows="1"
+            autosize
+            name="本发明的技术领域"
+            label="本发明的技术领域"
+            placeholder="本发明的技术领域"
+            :rules="[{ required: false, message: '本发明的技术领域' }]"
+          />
+          <van-field
+            v-model="form.questions.q2"
+            type="textarea"
+            rows="1"
+            autosize
+            name="与本发明相关的背景技术"
+            label="与本发明相关的背景技术"
+            placeholder="与本发明相关的背景技术"
+            :rules="[{ required: false, message: '与本发明相关的背景技术' }]"
+          />
+
+          <van-field
+            v-model="form.questions.q3"
+            type="textarea"
+            rows="1"
+            autosize
+            name="现有技术的缺点及本发明所要解决的技术问题"
+            label="现有技术的缺点及本发明所要解决的技术问题"
+            placeholder="现有技术的缺点及本发明所要解决的技术问题"
+            :rules="[{ required: false, message: '现有技术的缺点及本发明所要解决的技术问题' }]"
+          />
+          <van-field
+            v-model="form.questions.q4"
+            type="textarea"
+            rows="1"
+            autosize
+            name="本发明技术方案的详细阐述"
+            label="本发明技术方案的详细阐述"
+            placeholder="本发明技术方案的详细阐述"
+            :rules="[{ required: false, message: '本发明技术方案的详细阐述' }]"
+          />
+          <van-field
+            v-model="form.questions.q5"
+            type="textarea"
+            rows="1"
+            autosize
+            name="本申请的关键点和欲保护点"
+            label="本申请的关键点和欲保护点"
+            placeholder="本申请的关键点和欲保护点"
+            :rules="[{ required: false, message: '本申请的关键点和欲保护点' }]"
+          />
+          <van-field
+            v-model="form.questions.q6"
+            type="textarea"
+            rows="1"
+            autosize
+            name="与本发明最相似,相近的实现技术,方案相比,本发明有何优点"
+            label="与本发明最相似,相近的实现技术,方案相比,本发明有何优点"
+            placeholder="与本发明最相似,相近的实现技术,方案相比,本发明有何优点"
+            :rules="[{ required: false, message: '与本发明最相似,相近的实现技术,方案相比,本发明有何优点' }]"
+          />
+          <van-field
+            v-model="form.questions.q7"
+            type="textarea"
+            rows="1"
+            autosize
+            name="针对本发明技术方案,是否还有别的替代方案"
+            label="针对本发明技术方案,是否还有别的替代方案"
+            placeholder="针对本发明技术方案,是否还有别的替代方案"
+            :rules="[{ required: false, 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: adminLogin } = createNamespacedHelpers('adminLogin');
+export default {
+  name: 'detail-2',
+  props: {
+    form: { type: Object },
+  },
+  components: {},
+  data: function () {
+    return {
+      // 管理员信息
+      adminInfo: {},
+      // 申请类型
+      typePicker: false,
+      typeList: ['发明', '实用新型', '其他'],
+    };
+  },
+  created() {
+    this.search();
+  },
+  methods: {
+    ...adminLogin(['query']),
+    async search() {
+      let res = await this.query();
+      if (this.$checkRes(res)) {
+        let admin = res.data.find((i) => i.code == 'JLKJQY');
+        if (admin) {
+          this.$set(this, `adminInfo`, admin);
+          this.$set(this.form, `admin_id`, admin._id);
+        }
+      }
+    },
+    onSubmit() {
+      this.$emit('onSubmit', { data: this.form });
+    },
+    // 选择类型
+    typeCon(value) {
+      this.$set(this.form, `type`, value);
+      this.typePicker = false;
+    },
+  },
+  computed: {
+    ...mapState(['user']),
+  },
+  metaInfo() {
+    return { title: this.$route.meta.title };
+  },
+  watch: {
+    test: {
+      deep: true,
+      immediate: true,
+      handler(val) {},
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped></style>

+ 110 - 0
src/views/patent/user/apply/analysis/parts/list-2.vue

@@ -0,0 +1,110 @@
+<template>
+  <div id="list-2">
+    <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="result(item)">查看审核结果</van-button>
+            <van-button size="small" type="info" @click="downFile(item.file)" v-if="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-2',
+  props: {
+    list: { type: Array },
+  },
+  components: {},
+  data: function () {
+    return {};
+  },
+  created() {},
+  methods: {
+    // 整理状态
+    getStu(status) {
+      if (status == '0') return '已提交给管理员,请等待审核';
+      else if (status == '1') return '管理员审核通过,等待系统管理员发送报告文件!';
+      else if (status == '-1') return '管理员审核未通过,请查看审核意见,并重新提交申请';
+      else if (status == '2') return '文件已发送,请及时下载查看!';
+    },
+    result(data) {
+      this.$emit('result', data);
+    },
+    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: `非正常文件,无法下载` });
+      }
+    },
+  },
+  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>

+ 90 - 0
src/views/patent/user/apply/analysis/parts/result-2.vue

@@ -0,0 +1,90 @@
+<template>
+  <div id="result-1">
+    <van-row>
+      <van-col span="24" class="main">
+        <van-col span="24" class="one">
+          <van-form>
+            <van-field v-model="form.name" name="发明名称" label="发明名称" readonly />
+            <van-field v-model="form.apply_name" name="申请人" label="申请人" readonly />
+            <van-field v-model="form.type" name="专利类型" label="专利类型" readonly />
+            <van-field v-model="form.inventor" name="发明人" label="发明人" readonly />
+            <van-field v-model="form.contact" name="技术联系人" label="技术联系人" readonly />
+            <van-field v-model="form.phone" name="联系人电话" label="联系人电话" readonly />
+            <van-field v-model="form.email" name="联系人邮箱" label="联系人邮箱" readonly />
+            <div style="margin: 16px" v-if="form.status == '-1' || form.status == '-2'">
+              <van-button round block type="info" @click="update">重申</van-button>
+            </div>
+          </van-form>
+        </van-col>
+        <van-col span="24" class="two">
+          <van-divider :style="{ color: '#1989fa', borderColor: '#1989fa', padding: '0 16px' }"> 审核结果 </van-divider>
+          <van-col span="24" class="record">
+            <van-steps direction="vertical" inactive-color="#409eff">
+              <van-step v-for="(item, index) in form.record" :key="index">
+                <p>
+                  <span>{{ item.time }}</span>
+                  <span>{{ item.word }}</span>
+                </p>
+                <p>审核意见:{{ item.remark || '暂无' }}</p>
+              </van-step>
+            </van-steps>
+          </van-col>
+        </van-col>
+      </van-col>
+    </van-row>
+  </div>
+</template>
+
+<script>
+import { mapState, createNamespacedHelpers } from 'vuex';
+export default {
+  name: 'result-1',
+  props: {
+    form: { type: Object },
+  },
+  components: {},
+  data: function () {
+    return {};
+  },
+  created() {},
+  methods: {
+    update() {
+      this.$emit('update');
+    },
+  },
+  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 {
+    .record {
+      p:first-child {
+        color: #666;
+        font-weight: bold;
+        margin: 0 0 5px 0;
+        font-size: 12px;
+        span:last-child {
+          float: right;
+        }
+      }
+      p:last-child {
+        color: #000;
+      }
+    }
+  }
+}
+</style>

+ 69 - 0
src/views/patent/user/apply/analysis/result.vue

@@ -0,0 +1,69 @@
+<template>
+  <div id="result">
+    <admin-frame topType="2" @back="back" :usePage="false" :rightArrow="false" :useNav="false">
+      <template v-slot:info>
+        <result-2 :form="form" @update="update"></result-2>
+      </template>
+    </admin-frame>
+  </div>
+</template>
+
+<script>
+import result2 from './parts/result-2.vue';
+import adminFrame from '@frame/src/components/mobile-frame/mobile-main.vue';
+import { mapState, createNamespacedHelpers } from 'vuex';
+const { mapActions: patentanalysis } = createNamespacedHelpers('patentanalysis');
+export default {
+  name: 'result',
+  props: {},
+  components: {
+    adminFrame,
+    result2,
+  },
+  data: function () {
+    return {
+      form: {},
+    };
+  },
+  async created() {
+    if (this.id) await this.search();
+  },
+  methods: {
+    ...patentanalysis(['fetch']),
+    async search() {
+      let res = await this.fetch(this.id);
+      if (this.$checkRes(res)) {
+        this.$set(this, `form`, res.data);
+      }
+    },
+    // 重申
+    update() {
+      let { id } = this.form;
+      this.$router.push({ path: '/patent/user/apply/analysis/detail', query: { id: id } });
+    },
+
+    // 返回
+    back() {
+      this.$router.push({ path: '/patent/user/apply/analysis' });
+    },
+  },
+  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>

+ 103 - 0
src/views/patent/user/apply/apply/detail.vue

@@ -0,0 +1,103 @@
+<template>
+  <div id="detail">
+    <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 './parts/detail-1.vue';
+import adminFrame from '@frame/src/components/mobile-frame/mobile-main.vue';
+import { mapState, createNamespacedHelpers } from 'vuex';
+const { mapActions: patentapply } = createNamespacedHelpers('patentapply');
+var moment = require('moment');
+export default {
+  name: 'detail',
+  props: {},
+  components: {
+    adminFrame,
+    detail1,
+  },
+  data: function () {
+    return {
+      form: {},
+    };
+  },
+  async created() {
+    await this.search();
+  },
+  methods: {
+    ...patentapply(['fetch', 'create', 'update']),
+    async search() {
+      if (this.id) {
+        let res = await this.fetch(this.id);
+        if (this.$checkRes(res)) {
+          if (!res.data.questions) res.data.questions = {};
+          this.$set(this, `form`, res.data);
+        }
+      } else {
+        let data = {
+          inventor: [{ user_id: this.user._id, name: this.user.name }],
+          contact: [{ user_id: this.user._id, name: this.user.name }],
+          questions: {},
+          // water_number: moment(new Date()).valueOf(),
+          apply_name: this.user.name,
+          is_mech: '0',
+        };
+        this.$set(this, `form`, data);
+      }
+    },
+    async onSubmit({ data }) {
+      if (data.id) {
+        if (data.status == '-1') data.status = '0';
+        else if (data.status == '-2') data.status = '1';
+        let res = await this.update(data);
+        if (this.$checkRes(res)) {
+          this.$toast({ type: `success`, message: `修改专利申请成功` });
+          this.back();
+        } else {
+          this.$toast({ type: `success`, message: `${res.errmsg}` });
+        }
+      } else {
+        data.user_id = this.user._id;
+        // 不需要机构
+        if (data.is_mech == '0') data.status = '1';
+        // 需要机构
+        else if (data.is_mech == '1') data.status = '0';
+        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/user/apply/apply' });
+    },
+  },
+  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>

+ 71 - 0
src/views/patent/user/apply/apply/gzjDetail.vue

@@ -0,0 +1,71 @@
+<template>
+  <div id="detail">
+    <admin-frame @search="search" :limit="limit" :total="total" topType="2" @back="back" :rightArrow="false" :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: patentwarning } = createNamespacedHelpers('patentwarning');
+export default {
+  name: 'detail',
+  props: {},
+  components: {
+    adminFrame,
+    list2,
+  },
+  data: function () {
+    return {
+      list: [],
+      limit: 5,
+      total: 0,
+    };
+  },
+  async created() {
+    await this.search();
+  },
+  methods: {
+    ...patentwarning(['query']),
+    async search({ skip = 0, limit = this.limit, ...info } = {}) {
+      info.name = this.name;
+      info.create_number = this.create_number;
+      info.to_id = this.user._id;
+      let res = await this.query({ skip, limit, ...info });
+      if (this.$checkRes(res)) {
+        this.$set(this, `list`, res.data);
+      }
+    },
+    // 返回
+    back() {
+      window.history.back();
+    },
+  },
+  computed: {
+    ...mapState(['user']),
+    name() {
+      return this.$route.query.name;
+    },
+    create_number() {
+      return this.$route.query.create_number;
+    },
+  },
+  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/user/apply/apply/index.vue

@@ -0,0 +1,76 @@
+<template>
+  <div id="index">
+    <admin-frame @search="search" :limit="limit" :total="total" topType="2" @back="back" @add="add" :useNav="false">
+      <template v-slot:info>
+        <list-1 :list="list" @result="result" @gzjBtn="gzjBtn"></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: patentapply } = createNamespacedHelpers('patentapply');
+export default {
+  name: 'index',
+  props: {},
+  components: {
+    adminFrame,
+    list1,
+  },
+  data: function () {
+    return {
+      list: [],
+      limit: 5,
+      total: 0,
+    };
+  },
+  async created() {
+    await this.search();
+  },
+  methods: {
+    ...patentapply(['query']),
+    async search({ skip = 0, limit = this.limit, ...info } = {}) {
+      info.user_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);
+      }
+    },
+    // 添加
+    add() {
+      this.$router.push({ path: '/patent/user/apply/apply/detail' });
+    },
+    // 查看结果
+    result(data) {
+      this.$router.push({ path: '/patent/user/apply/apply/result', query: { id: data.id } });
+    },
+    // 查看国知局反馈信息
+    gzjBtn(data) {
+      this.$router.push({ path: '/patent/user/apply/apply/gzjDetail', query: { name: data.name, create_number: data.create_number } });
+    },
+    // 返回
+    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>

+ 407 - 0
src/views/patent/user/apply/apply/parts/detail-1.vue

@@ -0,0 +1,407 @@
+<template>
+  <div id="detail-1">
+    <van-row>
+      <van-col span="24" class="main">
+        <van-form>
+          <van-col :span="24" class="remark">用户申请专利如需所在学校机构进行审核,请选择是;如不需要请选择否;</van-col>
+          <van-field name="is_mech" label="是否需要机构" :rules="[{ required: false, message: '请选择' }]">
+            <template #input>
+              <van-radio-group v-model="form.is_mech" direction="horizontal">
+                <van-radio name="1">是</van-radio>
+                <van-radio name="0">否</van-radio>
+              </van-radio-group>
+            </template>
+          </van-field>
+          <van-field
+            v-if="form.is_mech == '1'"
+            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.water_number" name="专利用户码" label="专利用户码" readonly /> -->
+          <van-field v-model="form.name" name="专利名称" label="专利名称" placeholder="专利名称" :rules="[{ required: false, message: '专利名称' }]" />
+          <van-field v-model="form.apply_name" name="申请人" label="申请人" placeholder="申请人" :rules="[{ required: false, message: '申请人' }]" />
+          <van-field readonly clickable name="type" :value="form.type" label="选择类型" placeholder="点击选择" @click="typePicker = true" />
+          <van-popup v-model="typePicker" position="bottom">
+            <van-picker show-toolbar :columns="typeList" @confirm="typeCon" @cancel="typePicker = false" />
+          </van-popup>
+          <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-col span="24" class="inventor">
+            <van-col span="24" class="inventor_btn">
+              <van-button size="mini" type="info" @click="selectinventor('contact')">选择技术联系人</van-button>
+              <van-button size="mini" type="info" @click="addinventor('contact')">添加技术联系人</van-button>
+            </van-col>
+            <van-col span="24" class="inventor_list">
+              <span>技术联系人:</span>
+              <span v-for="(item, index) in form.contact" :key="index">
+                {{ index + 1 }}-{{ item.name }}- <span style="color: #ff0000" @click="delCon(item)">删除</span>;
+              </span>
+            </van-col>
+          </van-col>
+          <van-field v-model="form.phone" name="联系人电话" label="联系人电话" placeholder="联系人电话" :rules="[{ required: false, message: '联系人电话' }]" />
+          <van-field v-model="form.email" name="联系人邮箱" label="联系人邮箱" placeholder="联系人邮箱" :rules="[{ required: false, message: '联系人邮箱' }]" />
+          <van-field
+            v-model="form.questions.q8"
+            type="textarea"
+            rows="1"
+            autosize
+            name="特殊情况说明"
+            label="特殊情况说明"
+            placeholder="特殊情况说明"
+            :rules="[{ required: false, message: '特殊情况说明' }]"
+          />
+          <van-field
+            v-model="form.questions.q1"
+            type="textarea"
+            rows="1"
+            autosize
+            name="本发明的技术领域"
+            label="本发明的技术领域"
+            placeholder="本发明的技术领域"
+            :rules="[{ required: false, message: '本发明的技术领域' }]"
+          />
+          <van-field
+            v-model="form.questions.q2"
+            type="textarea"
+            rows="1"
+            autosize
+            name="与本发明相关的背景技术"
+            label="与本发明相关的背景技术"
+            placeholder="与本发明相关的背景技术"
+            :rules="[{ required: false, message: '与本发明相关的背景技术' }]"
+          />
+          <van-field
+            v-model="form.questions.q3"
+            type="textarea"
+            rows="1"
+            autosize
+            name="现有技术的缺点及本发明所要解决的技术问题"
+            label="现有技术的缺点及本发明所要解决的技术问题"
+            placeholder="现有技术的缺点及本发明所要解决的技术问题"
+            :rules="[{ required: false, message: '现有技术的缺点及本发明所要解决的技术问题' }]"
+          />
+          <van-field
+            v-model="form.questions.q4"
+            type="textarea"
+            rows="1"
+            autosize
+            name="本发明技术方案的详细阐述"
+            label="本发明技术方案的详细阐述"
+            placeholder="本发明技术方案的详细阐述"
+            :rules="[{ required: false, message: '本发明技术方案的详细阐述' }]"
+          />
+          <van-field
+            v-model="form.questions.q5"
+            type="textarea"
+            rows="1"
+            autosize
+            name="本申请的关键点和欲保护点"
+            label="本申请的关键点和欲保护点"
+            placeholder="本申请的关键点和欲保护点"
+            :rules="[{ required: false, message: '本申请的关键点和欲保护点' }]"
+          />
+          <van-field
+            v-model="form.questions.q6"
+            type="textarea"
+            rows="1"
+            autosize
+            name="与本发明最相似,相近的实现技术,方案相比,本发明有何优点"
+            label="与本发明最相似,相近的实现技术,方案相比,本发明有何优点"
+            placeholder="与本发明最相似,相近的实现技术,方案相比,本发明有何优点"
+            :rules="[{ required: false, message: '与本发明最相似,相近的实现技术,方案相比,本发明有何优点' }]"
+          />
+          <van-field
+            v-model="form.questions.q7"
+            type="textarea"
+            rows="1"
+            autosize
+            name="针对本发明技术方案,是否还有别的替代方案"
+            label="针对本发明技术方案,是否还有别的替代方案"
+            placeholder="针对本发明技术方案,是否还有别的替代方案"
+            :rules="[{ required: false, message: '针对本发明技术方案,是否还有别的替代方案' }]"
+          />
+          <van-field name="check_url" label="审查文件">
+            <template #input>
+              <van-uploader
+                :fileList="form.check_url"
+                :max-count="1"
+                :after-read="(file) => toUpload(file, 'check_url')"
+                @delete="(file) => toDelete(file, 'check_url')"
+                accept="file"
+              />
+            </template>
+          </van-field>
+          <div style="margin: 16px">
+            <van-button round block type="info" @click="onSubmit">提交</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>
+    <van-dialog class="adddialog" v-model="addShow" title="添加用户" :show-cancel-button="false" :show-confirm-button="false" :closeOnClickOverlay="true">
+      <van-form>
+        <van-field v-model="addForm.name" name="name" label="姓名" placeholder="姓名" />
+        <van-field v-model="addForm.phone" name="phone" label="联系电话" placeholder="联系电话" />
+        <van-col span="24" class="btn">
+          <van-button type="danger" size="small" @click="resetAdd">取消添加</van-button>
+          <van-button type="info" size="small" @click="submitAdd">确认添加</van-button>
+        </van-col>
+      </van-form>
+    </van-dialog>
+  </div>
+</template>
+
+<script>
+import { mapState, createNamespacedHelpers } from 'vuex';
+const { mapActions: adminLogin } = createNamespacedHelpers('adminLogin');
+const { mapActions: personal } = createNamespacedHelpers('personal');
+const { mapActions: upload } = createNamespacedHelpers('upload');
+export default {
+  name: 'detail-1',
+  props: {
+    form: { type: Object },
+  },
+  components: {},
+  data: function () {
+    return {
+      // 管理员信息
+      adminInfo: {},
+      // 选择机构
+      showPicker: false,
+      mechanismList: [],
+      // 申请类型
+      typePicker: false,
+      typeList: ['发明', '实用新型', '其他'],
+      // 选择发明人&&技术联系人
+      // 查询专利
+      show: false,
+      type: '',
+      // 属于手机号查询用户
+      searchName: '',
+      list: [],
+      limit: 4,
+      total: 0,
+      // 添加发明人&&技术联系人
+      addShow: false,
+      addForm: {},
+    };
+  },
+  created() {
+    this.searchUser();
+    this.search();
+  },
+  methods: {
+    ...upload(['upload']),
+    ...adminLogin(['query']),
+    ...personal({ perQuery: 'query' }),
+
+    async search() {
+      let res = await this.query();
+      if (this.$checkRes(res)) {
+        let admin = res.data.find((i) => i.code == 'JLKJQY');
+        if (admin) {
+          this.$set(this, `adminInfo`, admin);
+          this.$set(this.form, `admin_id`, admin._id);
+          let arr = await this.query({ role: '2', pid: admin.id, code: 'JLKJQYCGD' });
+          if (this.$checkRes(res)) {
+            this.$set(this, `mechanismList`, arr.data);
+          }
+        }
+      }
+    },
+    onSubmit() {
+      this.$emit('onSubmit', { data: this.form });
+    },
+    // 选择机构
+    mechanismCon(value) {
+      this.$set(this.form, `mechanism_name`, value.name);
+      this.$set(this.form, `mechanism_id`, value._id);
+      this.showPicker = false;
+    },
+    // 选择类型
+    typeCon(value) {
+      this.$set(this.form, `type`, value);
+      this.typePicker = false;
+    },
+    // 选择发明人&&技术联系人
+    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);
+      else if (this.type == 'contact') this.form.contact.push(user);
+      this.show = false;
+    },
+    // 查询用户
+    async searchUser({ skip = 0, limit = 5, ...info } = {}) {
+      info.code = this.user.code;
+      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);
+      }
+    },
+    // 添加发明人&&技术联系人
+    addinventor(type) {
+      this.$set(this, `type`, type);
+      this.addShow = true;
+    },
+    // 取消添加
+    resetAdd() {
+      this.addForm = {};
+      this.addShow = false;
+    },
+    // 确认添加
+    submitAdd() {
+      let data = this.addForm;
+      if (this.type == 'inventor') this.form.inventor.push(data);
+      else if (this.type == 'contact') this.form.contact.push(data);
+      this.addShow = false;
+    },
+    // 删除发明用户
+    delInv(data) {
+      this.form.inventor.splice(this.form.inventor.indexOf(data), 1);
+    },
+    // 删除技术联系人
+    delCon(data) {
+      this.form.contact.splice(this.form.contact.indexOf(data), 1);
+    },
+    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>
+.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;
+  }
+}
+.adddialog {
+  .btn {
+    margin: 8px 0;
+    text-align: center;
+    .van-button {
+      margin: 0 10px;
+    }
+  }
+}
+// 提醒信息
+.remark {
+  background-color: #ffffff;
+  padding: 8px;
+  font-size: 14px;
+  color: #ff0000;
+}
+</style>

+ 110 - 0
src/views/patent/user/apply/apply/parts/list-1.vue

@@ -0,0 +1,110 @@
+<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.water_number || '暂无' }}</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="result(item)">查看审核结果</van-button>
+            <van-button size="small" type="info" @click="gzjBtn(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: {
+    result(data) {
+      this.$emit('result', data);
+    },
+    // 国知局反馈信息
+    gzjBtn(data) {
+      this.$emit('gzjBtn', 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 '管理员审核未通过,请查看审核意见,并重新提交申请';
+    },
+  },
+  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>

+ 139 - 0
src/views/patent/user/apply/apply/parts/list-2.vue

@@ -0,0 +1,139 @@
+<template>
+  <div id="list-2">
+    <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 span="24" class="otherInfo">
+              发送时间:<span>{{ getDate(item.meta) }}</span>
+            </van-col>
+          </van-col>
+          <van-col span="24" class="btn">
+            <van-button size="small" type="info" @click="toView(item.file_url)">查看文件</van-button>
+          </van-col>
+        </van-col>
+      </van-col>
+    </van-row>
+    <van-dialog class="dialog" v-model="show" title="文件下载" :show-confirm-button="false" :show-cancel-button="true">
+      <van-col span="24" class="list" v-for="(item, index) in fileList" :key="index">
+        <van-col span="24" class="name"
+          >文件路径:<span>{{ item }}</span></van-col
+        >
+        <van-col span="24" class="btn">
+          <van-button type="info" size="small" @click="download(item)">下载文件</van-button>
+        </van-col>
+      </van-col>
+    </van-dialog>
+  </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 {
+      // 文件下载
+      show: false,
+      fileList: [],
+    };
+  },
+  created() {},
+  methods: {
+    // 查看文件
+    toView(data) {
+      this.$set(this, `fileList`, data);
+      this.show = true;
+    },
+    download(data) {
+      console.log(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 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;
+      }
+    }
+  }
+}
+.dialog {
+  padding: 0 8px;
+  /deep/.van-dialog__content {
+    height: 350px;
+    overflow-y: auto;
+  }
+  .list {
+    .name {
+      font-size: 14px;
+      word-break: break-all;
+      color: #666;
+      margin: 0 0 5px 0;
+      span {
+        color: #000;
+      }
+    }
+    .btn {
+      text-align: center;
+    }
+  }
+}
+</style>

+ 107 - 0
src/views/patent/user/apply/apply/parts/result-1.vue

@@ -0,0 +1,107 @@
+<template>
+  <div id="result-1">
+    <van-row>
+      <van-col span="24" class="main">
+        <van-col span="24" class="one">
+          <van-form>
+            <van-field v-model="form.name" name="发明名称" label="发明名称" readonly />
+            <van-field v-model="form.apply_name" name="申请人" label="申请人" readonly />
+            <van-field v-model="form.type" name="专利类型" label="专利类型" readonly />
+            <van-col span="24" class="other">
+              <span>发明人:</span><span v-for="(item, index) in form.inventor" :key="index">{{ item.name }};</span>
+            </van-col>
+            <van-col span="24" class="other">
+              <span>技术联系人:</span><span v-for="(item, index) in form.contact" :key="index">{{ item.name }};</span>
+            </van-col>
+            <van-field v-model="form.phone" name="联系人电话" label="联系人电话" readonly />
+            <van-field v-model="form.email" name="联系人邮箱" label="联系人邮箱" readonly />
+            <div style="margin: 16px" v-if="form.status == '-1' || form.status == '-2'">
+              <van-button round block type="info" @click="update">重申</van-button>
+            </div>
+          </van-form>
+        </van-col>
+        <van-col span="24" class="two">
+          <van-divider :style="{ color: '#1989fa', borderColor: '#1989fa', padding: '0 16px' }"> 审核结果 </van-divider>
+          <van-col span="24" class="record">
+            <van-steps direction="vertical" inactive-color="#409eff">
+              <van-step v-for="(item, index) in form.record" :key="index">
+                <p>
+                  <span>{{ item.time }}</span>
+                  <span>{{ item.word }}</span>
+                </p>
+                <p>审核意见:{{ item.remark || '暂无' }}</p>
+              </van-step>
+            </van-steps>
+          </van-col>
+        </van-col>
+      </van-col>
+    </van-row>
+  </div>
+</template>
+
+<script>
+import { mapState, createNamespacedHelpers } from 'vuex';
+export default {
+  name: 'result-1',
+  props: {
+    form: { type: Object },
+  },
+  components: {},
+  data: function () {
+    return {};
+  },
+  created() {},
+  methods: {
+    update() {
+      this.$emit('update');
+    },
+  },
+  computed: {
+    ...mapState(['user']),
+  },
+  metaInfo() {
+    return { title: this.$route.meta.title };
+  },
+  watch: {
+    test: {
+      deep: true,
+      immediate: true,
+      handler(val) {},
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped>
+.main {
+  .one {
+    .other {
+      background-color: #ffffff;
+      padding: 8px 18px;
+      span {
+        color: #666;
+        font-size: 15px;
+      }
+      span:last-child {
+        color: #000;
+      }
+    }
+  }
+  .two {
+    .record {
+      p:first-child {
+        color: #666;
+        font-weight: bold;
+        margin: 0 0 5px 0;
+        font-size: 12px;
+        span:last-child {
+          float: right;
+        }
+      }
+      p:last-child {
+        color: #000;
+      }
+    }
+  }
+}
+</style>

+ 68 - 0
src/views/patent/user/apply/apply/result.vue

@@ -0,0 +1,68 @@
+<template>
+  <div id="result">
+    <admin-frame topType="2" @back="back" :usePage="false" :rightArrow="false" :useNav="false">
+      <template v-slot:info>
+        <result-1 :form="form" @update="update"></result-1>
+      </template>
+    </admin-frame>
+  </div>
+</template>
+
+<script>
+import result1 from './parts/result-1.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: 'result',
+  props: {},
+  components: {
+    adminFrame,
+    result1,
+  },
+  data: function () {
+    return {
+      form: {},
+    };
+  },
+  async created() {
+    if (this.id) await this.search();
+  },
+  methods: {
+    ...patentapply(['fetch']),
+    async search() {
+      let res = await this.fetch(this.id);
+      if (this.$checkRes(res)) {
+        this.$set(this, `form`, res.data);
+      }
+    },
+    // 重申
+    update() {
+      let { id } = this.form;
+      this.$router.push({ path: '/patent/user/apply/apply/detail', query: { id: id } });
+    },
+    // 返回
+    back() {
+      this.$router.push({ path: '/patent/user/apply/apply' });
+    },
+  },
+  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>

+ 102 - 0
src/views/patent/user/apply/assessment/detail.vue

@@ -0,0 +1,102 @@
+<template>
+  <div id="detail">
+    <admin-frame topType="2" @back="back" :rightArrow="false" :usePage="false" :useNav="false">
+      <template v-slot:info>
+        <detail-3 :form="form" @onSubmit="onSubmit"></detail-3>
+      </template>
+    </admin-frame>
+  </div>
+</template>
+
+<script>
+import detail3 from './parts/detail-3.vue';
+import adminFrame from '@frame/src/components/mobile-frame/mobile-main.vue';
+import { mapState, createNamespacedHelpers } from 'vuex';
+const { mapActions: patentassess } = createNamespacedHelpers('patentassess');
+const { mapActions: adminLogin } = createNamespacedHelpers('adminLogin');
+export default {
+  name: 'detail',
+  props: {},
+  components: {
+    adminFrame,
+    detail3,
+  },
+  data: function () {
+    return {
+      // 管理员信息
+      adminInfo: {},
+      form: {},
+    };
+  },
+  async created() {
+    this.searchOther();
+    if (this.id) await this.search();
+  },
+  methods: {
+    ...patentassess(['fetch', 'create', 'update']),
+    ...adminLogin({ adminQuery: 'query' }),
+    async search() {
+      let res = await this.fetch(this.id);
+      if (this.$checkRes(res)) {
+        this.$set(this, `form`, res.data);
+      }
+    },
+    async onSubmit(data) {
+      if (this.id) {
+        let data = this.form;
+        data.status = '0';
+        let res = await this.update(data);
+        if (this.$checkRes(res)) {
+          this.$toast({ type: `success`, message: `价值评估重申成功` });
+          this.back();
+        } else {
+          this.$toast({ type: `success`, message: `${res.errmsg}` });
+        }
+      } else {
+        data.user_id = this.user.id;
+        data.admin_id = this.adminInfo._id;
+        data.status = '0';
+        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 searchOther() {
+      let res = await this.adminQuery();
+      if (this.$checkRes(res)) {
+        let admin = res.data.find((i) => i.code == 'JLKJQY');
+        if (admin) {
+          this.$set(this, `adminInfo`, admin);
+        }
+      }
+    },
+    // 返回
+    back() {
+      this.$router.push({ path: '/patent/user/apply/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></style>

+ 98 - 0
src/views/patent/user/apply/assessment/index.vue

@@ -0,0 +1,98 @@
+<template>
+  <div id="index">
+    <admin-frame @search="search" :limit="limit" :total="total" topType="2" @back="back" @add="add" :useNav="false">
+      <template v-slot:info>
+        <list-3 :list="list" @result="result" @view="toView"></list-3>
+      </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 list3 from './parts/list-3.vue';
+import info1 from './parts/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: 'index',
+  props: {},
+  components: {
+    adminFrame,
+    list3,
+    info1,
+  },
+  data: function () {
+    return {
+      list: [],
+      limit: 5,
+      total: 0,
+      // 专利详情
+      show: false,
+      info: {},
+    };
+  },
+  async created() {
+    await this.search();
+  },
+  methods: {
+    ...patentassess(['query']),
+    ...patentinfo(['fetch']),
+    async search({ skip = 0, limit = this.limit, ...info } = {}) {
+      info.user_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);
+      }
+    },
+    // 添加
+    add() {
+      this.$router.push({ path: '/patent/user/apply/assessment/detail' });
+    },
+    // 查看结果
+    result(data) {
+      this.$router.push({ path: '/patent/user/apply/assessment/result', 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;
+      }
+    },
+    // 返回
+    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;
+  }
+}
+</style>

+ 176 - 0
src/views/patent/user/apply/assessment/parts/detail-3.vue

@@ -0,0 +1,176 @@
+<template>
+  <div id="detail-3">
+    <van-row>
+      <van-col span="24" class="main">
+        <van-col span="24" class="showBtn" v-if="patent_id == null">
+          <van-button type="info" size="small" @click="show = true">查询专利</van-button>
+        </van-col>
+        <van-col span="24" class="one">
+          <van-form @submit="onSubmit">
+            <van-field v-model="form.patent_id" name="patent_id" label="专利id" style="display: none" />
+            <van-field v-model="form.patent_name" name="patent_name" label="专利名称" row="2" type="textarea" readonly />
+            <van-field name="is_money" label="是否缴费">
+              <template #input>
+                <van-radio-group v-model="form.is_money" direction="horizontal">
+                  <van-radio :name="true">已缴费</van-radio>
+                  <van-radio :name="false">未缴费</van-radio>
+                </van-radio-group>
+              </template>
+            </van-field>
+            <div style="margin: 5px 16px">
+              <van-button round block type="info" native-type="submit">提交</van-button>
+            </div>
+          </van-form>
+        </van-col>
+      </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="searchPatent">
+            <template #action>
+              <div @click="searchPatent">搜索</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">
+              <span>{{ item.name }}</span>
+              <van-button type="info" size="mini" @click="conFirm(item)">确定专利</van-button>
+            </van-col>
+          </van-col>
+          <van-col span="24" class="page">
+            <page @search="searchPatent" :limit="limit" :total="total"></page>
+          </van-col>
+        </van-col>
+      </van-col>
+    </van-dialog>
+  </div>
+</template>
+
+<script>
+import { mapState, createNamespacedHelpers } from 'vuex';
+const { mapActions: patentinfo } = createNamespacedHelpers('patentinfo');
+export default {
+  name: 'detail-3',
+  props: {
+    form: { type: Object },
+  },
+  components: {},
+  data: function () {
+    return {
+      // 查询专利
+      show: false,
+      // 搜索专利
+      searchName: '',
+      list: [],
+      limit: 6,
+      total: 0,
+    };
+  },
+  created() {
+    this.search();
+  },
+  methods: {
+    ...patentinfo(['query', 'fetch']),
+    async search({ skip = 0, limit = this.limit, ...info } = {}) {
+      if (this.patent_id) {
+        let res = await this.fetch(this.patent_id);
+        if (this.$checkRes(res)) {
+          this.$set(this.form, `patent_name`, res.data.name);
+          this.$set(this.form, `patent_id`, res.data._id);
+        }
+      }
+      info.user_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);
+      }
+    },
+    onSubmit(values) {
+      this.$emit('onSubmit', values);
+    },
+    // 搜索专利
+    async searchPatent({ skip = 0, limit = this.limit, ...info } = {}) {
+      if (this.searchName) {
+        info.name = this.searchName;
+        info.user_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);
+        }
+      } else {
+        this.$toast({ type: `fail`, message: `缺少搜索信息` });
+      }
+    },
+    conFirm(data) {
+      this.$set(this.form, `patent_name`, data.name);
+      this.$set(this.form, `patent_id`, data._id);
+      this.searchName = '';
+      this.list = [];
+      this.total = 0;
+      this.show = false;
+    },
+  },
+  computed: {
+    ...mapState(['user']),
+    patent_id() {
+      return this.$route.query.patent_id;
+    },
+  },
+  metaInfo() {
+    return { title: this.$route.meta.title };
+  },
+  watch: {
+    test: {
+      deep: true,
+      immediate: true,
+      handler(val) {},
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped>
+.main {
+  .showBtn {
+    text-align: center;
+    margin: 10px 0;
+  }
+  .two {
+    .two_1 {
+      text-align: center;
+      .van-button {
+        margin: 10px 0;
+      }
+    }
+    .two_2 {
+      .list {
+        background-color: #fff;
+        padding: 8px;
+        margin: 0 0 5px 0;
+        .name {
+          font-size: 14px;
+          line-height: 25px;
+          .van-button {
+            margin: 0 8px;
+            top: -5px;
+          }
+        }
+      }
+    }
+  }
+}
+.dialog {
+  /deep/.van-dialog__content {
+    height: 400px;
+    overflow-y: auto;
+  }
+}
+/deep/.van-dialog {
+  width: 95%;
+}
+</style>

+ 81 - 0
src/views/patent/user/apply/assessment/parts/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="代理机构" readonly />
+            <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>

+ 110 - 0
src/views/patent/user/apply/assessment/parts/list-3.vue

@@ -0,0 +1,110 @@
+<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">
+          <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>{{ 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" @click="result(item)">查看审核结果</van-button>
+            <van-button size="small" type="info" @click="download(item.report)" v-if="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-3',
+  props: {
+    list: { type: Array },
+  },
+  components: {},
+  data: function () {
+    return {};
+  },
+  created() {},
+  methods: {
+    result(data) {
+      this.$emit('result', 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 '审核拒绝';
+    },
+    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 {
+  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>

+ 101 - 0
src/views/patent/user/apply/assessment/parts/result-3.vue

@@ -0,0 +1,101 @@
+<template>
+  <div id="result-3">
+    <van-row>
+      <van-col span="24" class="main">
+        <van-col span="24" class="one">
+          <van-form>
+            <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">
+                  <van-radio :name="true">已缴费</van-radio>
+                  <van-radio :name="false">未缴费</van-radio>
+                </van-radio-group>
+              </template>
+            </van-field>
+            <div style="margin: 16px" v-if="form.status == '-1'">
+              <van-button round block type="info" @click="update">重申</van-button>
+            </div>
+          </van-form>
+        </van-col>
+        <van-col span="24" class="two">
+          <van-divider :style="{ color: '#1989fa', borderColor: '#1989fa', padding: '0 16px' }"> 审核结果 </van-divider>
+          <van-col span="24" class="record">
+            <van-steps direction="vertical" inactive-color="#409eff">
+              <van-step v-for="(item, index) in form.record" :key="index">
+                <p>
+                  <span>{{ item.time }}</span>
+                  <span>{{ item.word }}</span>
+                </p>
+                <p>审核意见:{{ item.remark || '暂无' }}</p>
+              </van-step>
+            </van-steps>
+          </van-col>
+        </van-col>
+      </van-col>
+    </van-row>
+  </div>
+</template>
+
+<script>
+import { mapState, createNamespacedHelpers } from 'vuex';
+export default {
+  name: 'result-3',
+  props: {
+    form: { type: Object },
+  },
+  components: {},
+  data: function () {
+    return {};
+  },
+  created() {},
+  methods: {
+    // 查看专利信息
+    view(patent_id) {
+      this.$emit('view', patent_id);
+    },
+    // 重申
+    update() {
+      this.$emit('update');
+    },
+  },
+  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 {
+    .record {
+      p:first-child {
+        color: #666;
+        font-weight: bold;
+        margin: 0 0 5px 0;
+        font-size: 12px;
+        span:last-child {
+          float: right;
+        }
+      }
+      p:last-child {
+        color: #000;
+      }
+    }
+  }
+}
+</style>

+ 92 - 0
src/views/patent/user/apply/assessment/result.vue

@@ -0,0 +1,92 @@
+<template>
+  <div id="result">
+    <admin-frame topType="2" @back="back" :usePage="false" :rightArrow="false" :useNav="false">
+      <template v-slot:info>
+        <result-3 :form="form" @update="update" @view="toView"></result-3>
+      </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 result3 from './parts/result-3.vue';
+import info1 from './parts/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: 'result',
+  props: {},
+  components: {
+    adminFrame,
+    result3,
+    info1,
+  },
+  data: function () {
+    return {
+      form: {},
+      // 专利详情
+      show: false,
+      info: {},
+    };
+  },
+  async created() {
+    await this.search();
+  },
+  methods: {
+    ...patentassess(['fetch']),
+    ...patentinfo({ infoFetch: 'fetch' }),
+    async search() {
+      let res = await this.fetch(this.id);
+      if (this.$checkRes(res)) {
+        this.$set(this, `form`, res.data);
+      }
+    },
+    update() {
+      let data = this.form;
+      this.$router.push({ path: '/patent/user/apply/assessment/detail', query: { id: data.id } });
+    },
+    // 查看专利信息
+    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/user/apply/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>

+ 48 - 0
src/views/patent/user/chat/index.vue

@@ -0,0 +1,48 @@
+<template>
+  <div id="index">
+    <admin-frame topType="2" @back="back" :rightArrow="false" :usePage="false" :useNav="false">
+      <template v-slot:info>
+        <frame-chat></frame-chat>
+      </template>
+    </admin-frame>
+  </div>
+</template>
+
+<script>
+import frameChat from '@/layout/chatCommon/chat.vue';
+import adminFrame from '@frame/src/components/mobile-frame/mobile-main.vue';
+import { mapState, createNamespacedHelpers } from 'vuex';
+export default {
+  name: 'index',
+  props: {},
+  components: {
+    adminFrame,
+    frameChat,
+  },
+  data: function () {
+    return {};
+  },
+  async created() {},
+  methods: {
+    // 返回
+    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>

+ 64 - 0
src/views/patent/user/message/notice.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-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 } = {}) {
+      info.to_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);
+      }
+    },
+    // 返回
+    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>

+ 95 - 0
src/views/patent/user/message/parts/list-1.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>

+ 92 - 0
src/views/patent/user/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>

+ 90 - 0
src/views/patent/user/message/parts/list-3.vue

@@ -0,0 +1,90 @@
+<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>{{ item.create_time || '暂无' }}</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';
+export default {
+  name: 'list-1',
+  props: {
+    list: { type: Array },
+  },
+  components: {},
+  data: function () {
+    return {};
+  },
+  created() {},
+  methods: {
+    update(data) {
+      this.$emit('update', 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 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>

+ 66 - 0
src/views/patent/user/message/read.vue

@@ -0,0 +1,66 @@
+<template>
+  <div id="index">
+    <admin-frame @search="search" :limit="limit" :total="total" topType="2" @back="back" :rightArrow="false" :useNav="false">
+      <template v-slot:info>
+        <list-1 :list="oneList"></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: patentexamine } = createNamespacedHelpers('patentexamine');
+export default {
+  name: 'index',
+  props: {},
+  components: {
+    adminFrame,
+    list1,
+  },
+  data: function () {
+    return {
+      limit: 5,
+      total: 0,
+      // 审核信息
+      oneList: [],
+    };
+  },
+  async created() {
+    this.search();
+  },
+  methods: {
+    ...patentexamine(['query', 'update']),
+    async search({ skip = 0, limit = this.limit, ...info } = {}) {
+      info.to = this.user.id;
+      info.is_read = true;
+      let res = await this.query({ skip, limit, ...info });
+      if (this.$checkRes(res)) {
+        this.$set(this, `oneList`, 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>

+ 74 - 0
src/views/patent/user/message/unRead.vue

@@ -0,0 +1,74 @@
+<template>
+  <div id="unRead">
+    <admin-frame @search="search" :limit="limit" :total="total" topType="2" @back="back" :rightArrow="false" :useNav="false">
+      <template v-slot:info>
+        <list-1 :list="oneList" @update="oneUpdate"></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: patentexamine } = createNamespacedHelpers('patentexamine');
+export default {
+  name: 'unRead',
+  props: {},
+  components: {
+    adminFrame,
+    list1,
+  },
+  data: function () {
+    return {
+      limit: 5,
+      total: 0,
+      // 审核信息
+      oneList: [],
+    };
+  },
+  async created() {
+    this.search();
+  },
+  methods: {
+    ...patentexamine(['query', 'update']),
+    async search({ skip = 0, limit = this.limit, ...info } = {}) {
+      info.to = this.user.id;
+      info.is_read = false;
+      let res = await this.query({ skip, limit, ...info });
+      if (this.$checkRes(res)) {
+        this.$set(this, `oneList`, res.data);
+        this.$set(this, `total`, res.total);
+      }
+    },
+    async oneUpdate(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>

+ 65 - 0
src/views/patent/user/patent/early/index.vue

@@ -0,0 +1,65 @@
+<template>
+  <div id="index">
+    <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: 'index',
+  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;
+      info.user_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);
+      }
+    },
+    // 返回
+    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>

+ 88 - 0
src/views/patent/user/patent/information/detail.vue

@@ -0,0 +1,88 @@
+<template>
+  <div id="detail">
+    <admin-frame topType="2" @back="back" :rightArrow="false" :usePage="false" :useNav="false">
+      <template v-slot:info>
+        <detail-1 :form="form"></detail-1>
+        <van-col span="24" class="one">
+          <van-divider :style="{ color: '#1989fa', borderColor: '#1989fa', padding: '0 16px' }">专利交易</van-divider>
+          <van-col span="24" class="one_1">
+            <van-button type="info" size="small" @click="assessment(form)">评估报告</van-button>
+            <van-button type="info" size="small" @click="trans(form)" v-if="form.trans_status == '0'">专利交易</van-button>
+          </van-col>
+        </van-col>
+      </template>
+    </admin-frame>
+  </div>
+</template>
+
+<script>
+import detail1 from './parts/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: 'detail',
+  props: {},
+  components: {
+    adminFrame,
+    detail1,
+  },
+  data: function () {
+    return {
+      form: {},
+    };
+  },
+  async created() {
+    if (this.id) await this.search();
+  },
+  methods: {
+    ...patentinfo(['fetch']),
+    async search() {
+      let res = await this.fetch(this.id);
+      if (this.$checkRes(res)) {
+        res.data.inventor = JSON.stringify(res.data.inventor.map((i) => i.name));
+        this.$set(this, `form`, res.data);
+      }
+    },
+    // 评估报告
+    assessment(data) {
+      this.$router.push({ path: '/patent/user/apply/assessment/detail', query: { patent_id: data.id } });
+    },
+    // 专利交易
+    trans(data) {
+      this.$router.push({ path: '/patent/user/patent/information/trans_create', query: { id: data.id } });
+    },
+    // 返回
+    back() {
+      this.$router.push({ path: '/patent/index' });
+    },
+  },
+  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>

+ 124 - 0
src/views/patent/user/patent/information/index.vue

@@ -0,0 +1,124 @@
+<template>
+  <div id="index">
+    <admin-frame @search="search" :limit="limit" :total="total" topType="2" @back="back" :rightArrow="false" :useNav="false">
+      <template v-slot:info>
+        <van-tabs v-model="active" @change="change" color="#409eff">
+          <van-tab :title="`已授权【${oneTotal}】`" name="有效">
+            <list-1 :list="list" @detail="detail" @gzjBtn="gzjBtn"></list-1>
+          </van-tab>
+          <van-tab :title="`已受理【${twoTotal}】`" name="审中">
+            <list-1 :list="list" @detail="detail" @gzjBtn="gzjBtn"></list-1>
+          </van-tab>
+          <van-tab :title="`已失效专利【${thrTotal}】`" name="失效">
+            <list-1 :list="list" @detail="detail" @gzjBtn="gzjBtn"></list-1>
+          </van-tab>
+        </van-tabs>
+      </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: patentinfo } = createNamespacedHelpers('patentinfo');
+const moment = require('moment');
+export default {
+  name: 'index',
+  props: {},
+  components: {
+    adminFrame,
+    list1,
+  },
+  data: function () {
+    return {
+      active: '有效',
+      list: [],
+      limit: 10,
+      total: 0,
+      oneTotal: 0,
+      twoTotal: 0,
+      thrTotal: 0,
+    };
+  },
+  async created() {
+    await this.search({ term: '有效' });
+    await this.searchTotal();
+  },
+  methods: {
+    ...patentinfo(['query']),
+    async search({ skip = 0, limit = this.limit, ...info } = {}) {
+      if (this.active == '有效') {
+        info.term = this.active;
+        info.user_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);
+        }
+      } else if (this.active == '审中') {
+        info.term = this.active;
+        info.user_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);
+        }
+      } else if (this.active == '失效') {
+        info.term = this.active;
+        info.user_id = this.user._id;
+        let res = await this.query({ skip, limit, ...info });
+        if (this.$checkRes(res)) {
+          let onDate = moment(new Date()).format('YYYY-MM-DD');
+          let data = res.data.filter((i) => i.lose_data <= onDate);
+          console.log(data);
+          // this.$set(this, `list`, res.data);
+          // this.$set(this, `total`, res.total);
+        }
+      }
+    },
+    // 查询总数
+    async searchTotal({ skip = 0, limit = this.limit, ...info } = {}) {
+      let res = await this.query({ skip, limit, term: '有效', user_id: this.user._id, ...info });
+      if (this.$checkRes(res)) this.$set(this, `oneTotal`, res.total);
+      res = await this.query({ skip, limit, term: '审中', user_id: this.user._id, ...info });
+      if (this.$checkRes(res)) this.$set(this, `twoTotal`, res.total);
+      res = await this.query({ skip, limit, term: '失效', user_id: this.user._id, ...info });
+      if (this.$checkRes(res)) this.$set(this, `thrTotal`, res.total);
+    },
+    // 详情
+    detail(data) {
+      this.$router.push({ path: '/patent/user/patent/information/detail', query: { id: data.id } });
+    },
+    // 查看国知局反馈信息
+    gzjBtn(data) {
+      this.$router.push({ path: '/patent/user/apply/apply/gzjDetail', query: { name: data.name, create_number: data.create_number } });
+    },
+    // 选择类型
+    change(name) {
+      this.$set(this, `active`, name);
+      this.search({ term: name });
+    },
+    // 返回
+    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>

+ 90 - 0
src/views/patent/user/patent/information/parts/detail-1.vue

@@ -0,0 +1,90 @@
+<template>
+  <div id="detail-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="form.term" name="term" label="专利有效性" />
+            <van-field v-model="form.name" name="name" label="名称" />
+            <van-field v-model="form.create_number" name="create_number" label="申请号" />
+            <van-field v-model="form.create_date" name="create_date" label="申请日" />
+            <van-field v-model="form.success_number" name="success_number" label="公开(公告)号" />
+            <van-field v-model="form.success_date" name="success_date" label="公开(公告)日" />
+            <van-field v-model="form.type" name="type" label="专利类型" />
+            <van-field v-model="form.inventor" name="inventor" label="发明人" />
+            <van-field v-model="form.address" name="address" label="发明人地址" />
+            <van-field v-model="form.apply_personal" name="apply_personal" 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="1" autosize type="textarea" />
+            <van-field name="trans_status" label="是否交易">
+              <template #input>
+                <van-radio-group v-model="form.trans_status" direction="horizontal" disabled>
+                  <van-radio name="0">未交易</van-radio>
+                  <van-radio name="1">已交易</van-radio>
+                </van-radio-group>
+              </template>
+            </van-field>
+          </van-form>
+        </van-col>
+      </van-col>
+    </van-row>
+  </div>
+</template>
+
+<script>
+import { mapState, createNamespacedHelpers } from 'vuex';
+export default {
+  name: 'detail-1',
+  props: { form: { type: Object } },
+  components: {},
+  data: function () {
+    return {
+      img_url: '',
+    };
+  },
+  created() {},
+  methods: {
+    searchImg(data) {
+      if (data.img_url) {
+        var url = data.img_url.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: {
+    form: {
+      deep: true,
+      immediate: true,
+      handler(val) {
+        this.searchImg(val);
+      },
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped>
+.main {
+  .one {
+    height: 220px;
+    border-bottom: 1px solid #f1f1f1;
+    .van-image {
+      width: 100%;
+      height: 219px;
+    }
+  }
+}
+</style>

+ 98 - 0
src/views/patent/user/patent/information/parts/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="info" size="small" @click="gzjBtn(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);
+    },
+    gzjBtn(data) {
+      this.$emit('gzjBtn', 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>

+ 100 - 0
src/views/patent/user/patent/information/parts/trans-1.vue

@@ -0,0 +1,100 @@
+<template>
+  <div id="trans-1">
+    <van-row>
+      <van-col span="24" class="main">
+        <van-form @submit="onSubmit">
+          <van-field v-model="form.user_id" name="user_id" label="用户id" readonly style="display: none" />
+          <van-field v-model="form.patent_id" name="patent_id" label="专利id" readonly style="display: none" />
+          <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="联系人" :rules="[{ required: true, message: '联系人' }]" />
+          <van-field v-model="form.phone" name="phone" label="联系电话" :rules="[{ required: true, message: '联系电话' }]" />
+          <van-field v-model="form.email" name="email" label="电子邮箱" :rules="[{ required: true, message: '电子邮箱' }]" />
+          <van-field v-model="form.budget" name="budget" type="digit" label="投资预算(万元)" :rules="[{ required: true, message: '投资预算' }]" />
+          <van-field name="type" label="交易类型">
+            <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 name="质押">质押</van-radio>
+              </van-radio-group>
+            </template>
+          </van-field>
+          <van-field name="is_report" label="评估报告">
+            <template #input>
+              <van-radio-group v-model="form.is_report" direction="horizontal">
+                <van-radio :name="true">有</van-radio>
+                <van-radio :name="false">无</van-radio>
+              </van-radio-group>
+            </template>
+          </van-field>
+          <van-field name="report" label="评估报告">
+            <template #input>
+              <van-uploader
+                :fileList="form.report"
+                :max-count="1"
+                :after-read="(file) => toUpload(file, 'report')"
+                @delete="(file) => toDelete(file, 'report')"
+              />
+            </template>
+          </van-field>
+          <van-field v-model="form.requirementdesc" name="requirementdesc" label="技术说明" rows="2" autosize type="textarea" />
+          <van-field v-model="form.expect" name="expect" label="商业预期" rows="2" autosize type="textarea" />
+          <van-field v-model="form.condition" name="condition" label="合作条件及要求" rows="2" autosize type="textarea" />
+          <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');
+export default {
+  name: 'trans-1',
+  props: {
+    form: { type: Object },
+  },
+  components: {},
+  data: function () {
+    return {};
+  },
+  created() {},
+  methods: {
+    ...upload(['upload']),
+    onSubmit(values) {
+      this.$emit('onSubmit', values);
+    },
+    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>

+ 111 - 0
src/views/patent/user/patent/information/trans_create.vue

@@ -0,0 +1,111 @@
+<template>
+  <div id="detail">
+    <admin-frame topType="2" @back="back" :rightArrow="false" :usePage="false" :useNav="false">
+      <template v-slot:info>
+        <trans-1 :form="form" @onSubmit="onSubmit"></trans-1>
+      </template>
+    </admin-frame>
+  </div>
+</template>
+
+<script>
+import trans1 from './parts/trans-1.vue';
+import adminFrame from '@frame/src/components/mobile-frame/mobile-main.vue';
+import { mapState, createNamespacedHelpers } from 'vuex';
+const { mapActions: patentinfo } = createNamespacedHelpers('patentinfo');
+const { mapActions: patenttrans } = createNamespacedHelpers('patenttrans');
+const { mapActions: patentassess } = createNamespacedHelpers('patentassess');
+const { mapActions: adminLogin } = createNamespacedHelpers('adminLogin');
+export default {
+  name: 'detail',
+  props: {},
+  components: {
+    adminFrame,
+    trans1,
+  },
+  data: function () {
+    return {
+      // 机构信息
+      adminInfo: {},
+      // 专利信息
+      info: {},
+      // 发起交易
+      form: {},
+    };
+  },
+  async created() {
+    this.searchOther();
+    if (this.id) await this.search();
+  },
+  methods: {
+    ...patenttrans(['create']),
+    ...patentinfo(['fetch']),
+    ...patentassess({ assessQuery: 'query' }),
+    ...adminLogin({ adminQuery: 'query' }),
+    async search() {
+      let res = await this.fetch(this.id);
+      if (this.$checkRes(res)) {
+        this.$set(this, `info`, res.data);
+        let data = {
+          user_id: this.user._id,
+          patent_id: this.info._id,
+          create_number: this.info.create_number,
+          patent_name: this.info.name,
+          contact: this.user.name,
+        };
+        let arr = await this.assessQuery({ patent_id: this.info._id, user_id: this.user._id });
+        if (this.$checkRes(arr)) {
+          if (arr.data.length > 0) {
+            data.is_report = true;
+            data.report = arr.data[0].report;
+          } else {
+            data.is_report = false;
+          }
+          this.$set(this, `form`, data);
+        }
+      }
+    },
+    // 发起交易
+    async onSubmit(data) {
+      data.status = '0';
+      data.admin_id = this.adminInfo._id;
+      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/user/patent/information' });
+    },
+    // 查询其他信息
+    async searchOther() {
+      let res = await this.adminQuery({ code: this.user.code });
+      if (this.$checkRes(res)) {
+        this.$set(this, `adminInfo`, res.data[0]);
+      }
+    },
+  },
+  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>

+ 53 - 0
src/views/patent/user/patent/navigation/index.vue

@@ -0,0 +1,53 @@
+<template>
+  <div id="index">
+    <admin-frame @search="search" :limit="limit" :total="total" topType="2" @back="back" :rightArrow="false" :useNav="false">
+      <template v-slot:info> 专利导航 </template>
+    </admin-frame>
+  </div>
+</template>
+
+<script>
+import adminFrame from '@frame/src/components/mobile-frame/mobile-main.vue';
+import { mapState, createNamespacedHelpers } from 'vuex';
+
+export default {
+  name: 'index',
+  props: {},
+  components: {
+    adminFrame,
+  },
+  data: function () {
+    return {
+      list: [],
+      limit: 5,
+      total: 0,
+    };
+  },
+  async created() {
+    await this.search();
+  },
+  methods: {
+    async search({ skip = 0, limit = this.limit, ...info } = {}) {},
+
+    // 返回
+    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>

+ 83 - 0
src/views/patent/user/patent/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>

+ 102 - 0
src/views/patent/user/transaction/contract.vue

@@ -0,0 +1,102 @@
+<template>
+  <div id="contract">
+    <admin-frame topType="2" @back="back" :rightArrow="false" :usePage="false" :useNav="false">
+      <template v-slot:info>
+        <form-1 :form="form" @onSubmit="onSubmit"></form-1>
+      </template>
+    </admin-frame>
+  </div>
+</template>
+
+<script>
+import form1 from './parts/form-1.vue';
+import adminFrame from '@frame/src/components/mobile-frame/mobile-main.vue';
+import { mapState, createNamespacedHelpers } from 'vuex';
+const { mapActions: patenttrans } = createNamespacedHelpers('patenttrans');
+const { mapActions: adminLogin } = createNamespacedHelpers('adminLogin');
+export default {
+  name: 'contract',
+  props: {},
+  components: {
+    adminFrame,
+    form1,
+  },
+  data: function () {
+    return {
+      // 专利交易详情
+      info: {},
+      form: {},
+    };
+  },
+  async created() {
+    await this.search();
+  },
+  methods: {
+    ...patenttrans(['fetch', 'update']),
+    ...adminLogin({ adminQuery: 'query', adminFetch: 'fetch' }),
+    async search() {
+      let res = await this.fetch(this.id);
+      if (this.$checkRes(res)) {
+        this.$set(this, `info`, res.data);
+        if (this.info.status == '0') {
+          this.searchForm();
+        } else {
+          this.$set(this, `form`, res.data.contract);
+        }
+      }
+    },
+    // 整理form
+    async searchForm() {
+      // "INVESTORS"
+      let user = this.user;
+      let res = await this.adminQuery({ code: user.code });
+      if (this.$checkRes(res)) {
+        let admin = res.data[0];
+        let data = {
+          transfer_id: admin._id,
+          transfer: admin.deptname,
+          patent_id: this.info.patent_id,
+          create_number: this.info.create_number,
+          patent_name: this.info.patent_name,
+        };
+        this.$set(this, `form`, data);
+      }
+    },
+    async onSubmit(contract) {
+      let data = this.info;
+      data.is_contract = '1';
+      data.contract = contract;
+      data.status = '1';
+      let res = await this.update(data);
+      if (this.$checkRes(res)) {
+        this.$toast({ type: `success`, message: `填写合同成功` });
+        this.back();
+      } else {
+        this.$toast({ type: `success`, message: `${res.errmsg}` });
+      }
+    },
+    // 返回
+    back() {
+      window.history.go(-1);
+    },
+  },
+  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>

+ 75 - 0
src/views/patent/user/transaction/index.vue

@@ -0,0 +1,75 @@
+<template>
+  <div id="index">
+    <admin-frame @search="search" :limit="limit" :total="total" topType="2" @back="back" :rightArrow="false" :useNav="false">
+      <template v-slot:info>
+        <list-1 :list="list" @detail="detail"></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: 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 } = {}) {
+      if (this.type) info.type = this.type;
+      info.user_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);
+      }
+    },
+    // 查看详情
+    detail(data) {
+      this.$router.push({ path: '/patent/user/transaction/info', query: { id: data.id, type: this.type } });
+    },
+    add() {
+      this.$router.push({ path: '/patent/user/transaction/sell/detail' });
+    },
+    // 返回
+    back() {
+      this.$router.push({ path: '/patent/index' });
+    },
+  },
+  computed: {
+    ...mapState(['user']),
+    type() {
+      return this.$route.query.type;
+    },
+  },
+  metaInfo() {
+    return { title: this.$route.meta.title };
+  },
+  watch: {
+    test: {
+      deep: true,
+      immediate: true,
+      handler(val) {},
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped></style>

+ 173 - 0
src/views/patent/user/transaction/info.vue

@@ -0,0 +1,173 @@
+<template>
+  <div id="detail">
+    <admin-frame topType="2" @back="back" :rightArrow="false" :usePage="false" :useNav="false">
+      <template v-slot:info>
+        <info-1 :form="form" @addContract="addContract" @revoke="revoke" @confirm="confirm" @endTrans="endTrans"></info-1>
+      </template>
+    </admin-frame>
+    <van-dialog class="dialog" v-model="show" title="上传合同" :show-confirm-button="false" :show-cancel-button="false">
+      <van-form>
+        <van-field v-model="contartForm.patent_name" name="专利名称" label="专利名称" row="1" type="textarea" />
+        <van-field name="offine_contract" label="合同">
+          <template #input>
+            <van-uploader
+              :fileList="contartForm.offine_contract"
+              :max-count="1"
+              :after-read="(file) => toUpload(file, 'offine_contract')"
+              @delete="(file) => toDelete(file, 'offine_contract')"
+            />
+          </template>
+        </van-field>
+        <van-col span="24" class="btn">
+          <van-button type="info" size="small" @click="onSubmit">提交合同</van-button>
+          <van-button type="danger" size="small" @click="resetBtn">取消提交</van-button>
+        </van-col>
+      </van-form>
+    </van-dialog>
+  </div>
+</template>
+
+<script>
+import info1 from './parts/info-1.vue';
+import adminFrame from '@frame/src/components/mobile-frame/mobile-main.vue';
+import { mapState, createNamespacedHelpers } from 'vuex';
+const { mapActions: patenttrans } = createNamespacedHelpers('patenttrans');
+const { mapActions: patentinfo } = createNamespacedHelpers('patentinfo');
+const { mapActions: upload } = createNamespacedHelpers('upload');
+var moment = require('moment');
+export default {
+  name: 'detail',
+  props: {},
+  components: {
+    adminFrame,
+    info1,
+  },
+  data: function () {
+    return {
+      form: {},
+      // 结束交易
+      show: false,
+      contartForm: {},
+    };
+  },
+  async created() {
+    await this.search();
+  },
+  methods: {
+    ...upload(['upload']),
+    ...patenttrans(['fetch', 'update', 'check']),
+    ...patentinfo({ infoUpdate: 'update' }),
+    async search() {
+      let res = await this.fetch(this.id);
+      if (this.$checkRes(res)) {
+        this.$set(this, `form`, res.data);
+      }
+    },
+    // 填写合同
+    addContract() {
+      let data = this.form;
+      this.$router.push({ path: '/patent/user/transaction/contract', query: { id: data.id } });
+    },
+    // 撤销交易
+    async revoke() {
+      let data = this.form;
+      data.isdel = '1';
+      let res = await this.update(data);
+      if (this.$checkRes(res)) {
+        this.$toast({ type: `success`, message: `撤销交易成功` });
+        this.back();
+      } else {
+        this.$toast({ type: `success`, message: `${res.errmsg}` });
+      }
+    },
+    // 确认
+    async confirm() {
+      let data = this.form;
+      data.status = '3';
+      let res = await this.check(data);
+      if (this.$checkRes(res)) {
+        this.$toast({ type: `success`, message: `用户确认成功,待机构审核通过,交易结束` });
+        this.back();
+      } else {
+        this.$toast({ type: `success`, message: `${res.errmsg}` });
+      }
+    },
+    // 结束交易
+    endTrans() {
+      this.$set(this, `contartForm`, this.form);
+      this.show = true;
+    },
+    // 提交合同
+    async onSubmit() {
+      let data = this.contartForm;
+      data.is_contract = '0';
+      data.status = '4';
+      let res = await this.update(data);
+      if (this.$checkRes(res)) {
+        let arr = await this.infoUpdate({ id: data.patent_id, trans_status: '1' });
+        if (this.$checkRes(arr)) {
+          this.$toast({ type: `success`, message: `合同上传成功,交易完成` });
+          this.back();
+        }
+      } else {
+        this.$toast({ type: `success`, message: `${res.errmsg}` });
+      }
+    },
+    // 取消提交
+    resetBtn() {
+      this.contartForm = {};
+      this.show = false;
+    },
+    // 返回
+    back() {
+      this.$router.push({ path: '/patent/user/transaction/index', query: { type: this.type } });
+    },
+    async toUpload({ file }, model) {
+      // 上传,赋值
+      const res = await this.upload({ file, dir: 'file' });
+      if (this.$checkRes(res)) {
+        this.$set(this.contartForm, model, [{ name: res.name, url: res.uri }]);
+      }
+    },
+    toDelete(file, model) {
+      const index = this.contartForm[model].findIndex((f) => _.isEqual(f, file));
+      this.contartForm[model].splice(index, 1);
+    },
+  },
+  computed: {
+    ...mapState(['user']),
+    id() {
+      return this.$route.query.id;
+    },
+    type() {
+      return this.$route.query.type;
+    },
+  },
+  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: 250px;
+    overflow-y: auto;
+  }
+  .btn {
+    text-align: center;
+    margin: 15px 0;
+    .van-button {
+      margin: 0 10px;
+    }
+  }
+}
+</style>

+ 186 - 0
src/views/patent/user/transaction/parts/form-1.vue

@@ -0,0 +1,186 @@
+<template>
+  <div id="form-1">
+    <van-row>
+      <van-col span="24" class="main">
+        <van-col span="24" class="one">
+          <van-form @submit="onSubmit">
+            <van-field v-model="form.patent_id" name="patent_id" label="专利id" style="display: none" />
+            <van-field v-model="form.transfer_id" name="transfer_id" label="机构id" style="display: none" />
+            <van-col span="24" class="one_1"> 专利转让合同 </van-col>
+            <van-col span="24" class="one_2">
+              <span>甲方(转让方):</span>
+              <van-field v-model="form.transfer" name="transfer" />
+            </van-col>
+            <van-col span="24" class="one_2">
+              <span>乙方(受让方):</span>
+              <van-field v-model="form.transferee" name="transferee" />
+            </van-col>
+            <van-col span="24" class="one_3"> 甲、乙方经过平等协商,自愿订立专利权转让合同,并共同遵照执行: </van-col>
+            <van-col span="24" class="one_4">
+              <span>第一条 甲方将其享有的</span>
+              <van-field v-model="form.patent_name" name="patent_name" />
+              <span>专利权有偿转让给乙方,专利号为:</span>
+              <van-field v-model="form.create_number" name="create_number" />
+            </van-col>
+            <van-col span="24" class="one_5">
+              <span>第二条 甲方向乙方转让</span>
+              <van-field v-model="form.patent_right" name="patent_right" />
+              <span>专利权;</span>
+            </van-col>
+            <van-col span="24" class="one_6">
+              <span>第三条 乙方为此向甲方支付专利权转让费用</span>
+              <van-field v-model="form.money" name="money" />
+              <span>元,于本合同生效后</span>
+              <van-field v-model="form.days" name="days" />
+              <span>天内一次付清。</span>
+            </van-col>
+            <van-col span="24" class="one_7">第四条 如任何一方违反本合同约定给对方造成损失,守约方可以要求对方承担违约责任;</van-col>
+            <van-col span="24" class="one_7">第五条 甲方保证此转让行为不侵犯任何第三方的合法权益;</van-col>
+            <van-col span="24" class="one_7">第六条 本合同于各方签字盖章后生效,未经各方同意,任何一方均无权修改或变更本合同约定;</van-col>
+            <van-col span="24" class="one_8">
+              <span>第七条 任何因本合同的履行而产生的争议,均应当友好协商解决,如无法协商解决,各方同意交由</span>
+              <van-field v-model="form.arbirate" name="arbirate" />
+              <span>仲裁委员会按照该会现时有效的仲裁规则予以仲裁;</span>
+            </van-col>
+            <van-col span="24" class="one_7"> 第八条 本合同一式三份,双方各执一份,备案一份。 </van-col>
+            <van-col span="24" class="btn">
+              <van-button round block type="info" native-type="submit">提交</van-button>
+            </van-col>
+          </van-form>
+        </van-col>
+      </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>
+.main {
+  .one {
+    padding: 0 5px;
+    font-size: 16px;
+    .one_1 {
+      text-align: center;
+      font-weight: bold;
+      margin: 8px 0 8px 0;
+    }
+    .one_2 {
+      margin: 0 0 8px 0;
+      span {
+        float: left;
+        padding: 7px 0;
+      }
+      /deep/.van-cell {
+        float: left;
+        width: 68%;
+        padding: 5px;
+        border-bottom: 1px solid #000;
+        background-color: transparent;
+      }
+    }
+    .one_3 {
+      margin: 0 0 8px 0;
+    }
+    .one_4 {
+      margin: 0 0 8px 0;
+      span {
+        float: left;
+        padding: 7px 0;
+      }
+      /deep/.van-cell {
+        float: left;
+        width: 50%;
+        padding: 5px;
+        border-bottom: 1px solid #000;
+        background-color: transparent;
+      }
+      /deep/.van-cell:last-child {
+        width: 100%;
+      }
+    }
+    .one_5 {
+      margin: 0 0 8px 0;
+      span {
+        float: left;
+        padding: 7px 0;
+      }
+      /deep/.van-cell {
+        float: left;
+        width: 53%;
+        padding: 5px;
+        border-bottom: 1px solid #000;
+        background-color: transparent;
+      }
+    }
+    .one_6 {
+      margin: 0 0 8px 0;
+      span {
+        float: left;
+        padding: 7px 0;
+      }
+      /deep/.van-cell {
+        float: left;
+        width: 12%;
+        padding: 5px;
+        border-bottom: 1px solid #000;
+        background-color: transparent;
+      }
+      /deep/.van-cell:last-child {
+        width: 12%;
+      }
+    }
+    .one_7 {
+      margin: 0 0 8px 0;
+    }
+    .one_8 {
+      margin: 0 0 8px 0;
+      span {
+        float: left;
+        padding: 7px 0;
+      }
+      /deep/.van-cell {
+        float: left;
+        width: 100%;
+        padding: 5px;
+        border-bottom: 1px solid #000;
+        background-color: transparent;
+      }
+    }
+    .btn {
+      margin: 8px 0;
+    }
+  }
+}
+</style>

+ 112 - 0
src/views/patent/user/transaction/parts/info-1.vue

@@ -0,0 +1,112 @@
+<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-field name="status" label="状态">
+              <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 name="-1">填写合同审核失败,重填</van-radio>
+                  <van-radio name="2">合同审核通过,用户确认</van-radio>
+                  <van-radio name="3">用户确认成功,机构归档</van-radio>
+                  <van-radio name="-3">归档失败</van-radio>
+                  <van-radio name="4">归档成功</van-radio>
+                </van-radio-group>
+              </template>
+            </van-field> -->
+          </van-form>
+        </van-col>
+        <van-col span="24" class="two" v-if="useBtn == true">
+          <van-button type="info" size="small" @click="addContract" v-if="form.status == '0' || form.status == '-1'">填写合同</van-button>
+          <van-button type="danger" size="small" @click="revoke" v-if="form.status == '0'">撤回交易</van-button>
+          <van-button type="info" size="small" @click="confirm" v-if="form.status == '2'">用户确认</van-button>
+          <van-button type="info" size="small" @click="endTrans" v-if="form.status == '0'">结束交易</van-button>
+        </van-col>
+      </van-col>
+    </van-row>
+  </div>
+</template>
+
+<script>
+import { mapState, createNamespacedHelpers } from 'vuex';
+export default {
+  name: 'info-1',
+  props: {
+    form: { type: Object },
+    useBtn: { type: Boolean, default: () => true },
+  },
+  components: {},
+  data: function () {
+    return {};
+  },
+  created() {},
+  methods: {
+    // 填写合同
+    addContract() {
+      this.$emit('addContract');
+    },
+    // 撤回交易
+    revoke() {
+      this.$emit('revoke');
+    },
+    // 用户确认
+    confirm() {
+      this.$emit('confirm');
+    },
+    // 结束交易
+    endTrans() {
+      this.$emit('endTrans');
+    },
+    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>

+ 98 - 0
src/views/patent/user/transaction/parts/list-1.vue

@@ -0,0 +1,98 @@
+<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="12" class="otherInfo">
+              交易类型:<span>{{ item.type || '暂无' }}</span>
+            </van-col>
+            <van-col span="12" class="otherInfo">
+              投资预算:<span>{{ item.budget || '暂无' }}万元</span>
+            </van-col>
+            <van-col span="24" class="otherInfo">
+              状态:<span>{{ getStu(item.status) }}</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);
+    },
+    // 整理状态
+    getStu(data) {
+      if (data == '0') return '待交易';
+      else if (data == '1') return '填写完合同,等待机构审核';
+      else if (data == '-1') return '填写合同审核失败,重填';
+      else if (data == '2') return '合同审核通过,待用户确认';
+      else if (data == '3') return '用户确认成功,机构归档';
+      else if (data == '-3') return '归档失败';
+      else if (data == '4') 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;
+        }
+      }
+    }
+  }
+}
+</style>

+ 4 - 5
src/views/patent/user/userBtn.vue

@@ -145,18 +145,17 @@ export default {
     },
     pathBtn(type, path, query) {
       if (this.user) {
-        this.$router.push({ path: `/service/patent/${type}/${path}?${query}` });
+        this.$router.push({ path: `/patent/${type}/${path}?${query}` });
       } else {
-        this.$router.push({ path: '/login', query: { path: '/service/patent/index', type: '1' } });
+        this.$router.push({ path: '/login' });
       }
     },
     chat() {
-      // this.chatShow = true;
-      this.$router.push({ path: '/service/patent/user/chat/index' });
+      this.$router.push({ path: '/patent/user/chat/index' });
     },
     // 更多
     more() {
-      this.$router.push({ path: '/service/patent/market/index' });
+      this.$router.push({ path: '/patent/market/index' });
     },
   },
   computed: {