zhaogongxue преди 11 месеца
родител
ревизия
cf3ec60e18
променени са 42 файла, в които са добавени 2502 реда и са изтрити 469 реда
  1. 0 1
      dist/assets/chat.83f0e689.css
  2. 0 0
      dist/assets/edit.8e1f6c2e.css
  3. 0 0
      dist/assets/inviteinfo.82fcb43f.css
  4. BIN
      dist/assets/logo.03d6d6da.png
  5. 2 2
      dist/index.html
  6. 1 1
      src/api/private.js
  7. 1 1
      src/components/ActivateMembership/index.vue
  8. 130 100
      src/components/ChooseSubjectToTalk/index.vue
  9. 28 6
      src/components/Comments/index.vue
  10. 41 8
      src/components/Comments/row.vue
  11. 72 3
      src/components/IndexSection/index.vue
  12. 11 2
      src/components/IndexTitle/index.vue
  13. 1 1
      src/components/MomentLayout/com.vue
  14. 105 23
      src/components/MomentLayout/index.vue
  15. 21 2
      src/components/UserCard/index.vue
  16. 82 12
      src/components/layouts/Header.vue
  17. 15 7
      src/components/layouts/HeaderEditor.vue
  18. 0 1
      src/components/layouts/LayoutEditor.vue
  19. 0 1
      src/components/layouts/LayoutHeader.vue
  20. 1 1
      src/router/index.js
  21. 2 1
      src/useHook/useForum.js
  22. 1 1
      src/utils/constance.js
  23. 184 102
      src/views/forum/edit.vue
  24. 283 4
      src/views/forum/index.vue
  25. 8 6
      src/views/forum/topic.vue
  26. 523 7
      src/views/index/components/SigninPrize.vue
  27. 295 1
      src/views/index/content.vue
  28. 17 33
      src/views/index/follow.vue
  29. 81 28
      src/views/market/placeOrder.vue
  30. 60 5
      src/views/personal/components/ExperienceCard.vue
  31. 22 2
      src/views/personal/components/qiandao.vue
  32. 14 5
      src/views/personal/components/sett.vue
  33. 2 0
      src/views/personal/components/wallet.vue
  34. 19 4
      src/views/personal/foot.vue
  35. 122 32
      src/views/personal/index.vue
  36. 1 3
      src/views/personal/inviteinfo.vue
  37. 16 1
      src/views/personal/make.vue
  38. 11 4
      src/views/postDetail.vue
  39. 134 13
      src/views/sundry/editor.vue
  40. 188 37
      src/views/tongzhi/chat.vue
  41. 4 3
      src/views/tongzhi/components/comment.vue
  42. 4 5
      src/views/tongzhi/components/inform.vue

+ 0 - 1
dist/assets/chat.83f0e689.css

@@ -1 +0,0 @@
-.namea[data-v-0471d126]{font-family:PingFangSC,PingFang SC;font-weight:500;font-size:14px;color:#222;line-height:20px;text-align:left;font-style:normal}.timea[data-v-0471d126]{font-family:SFPro,SFPro;font-weight:400;font-size:12px;color:#666;line-height:14px;text-align:left;font-style:normal}.cona[data-v-0471d126]{font-family:SFPro,SFPro;font-weight:400;font-size:14px;color:#222;line-height:16px;text-align:left;font-style:normal}.name[data-v-0471d126]{font-family:PingFangSC,PingFang SC;font-weight:500;font-size:14px;color:#222;line-height:20px;text-align:left;font-style:normal}.box[data-v-0471d126]{height:115px;border-bottom:1px solid #ebebeb;padding:24px;box-sizing:border-box;display:flex}.btn[data-v-0471d126]{width:104px;height:40px;background:#cacaca;border-radius:4px;font-family:PingFangSC,PingFang SC;font-weight:400;font-size:14px;color:#fff;line-height:40px;text-align:center;font-style:normal;margin-top:16px}.lefta[data-v-0471d126]{background:#f5f5f5;border-radius:4px}.righta[data-v-0471d126]{background:rgba(0,176,176,.06);border-radius:4px}.conten[data-v-0471d126]{padding:9px 12px;font-family:PingFangSC,PingFang SC;font-weight:400;font-size:14px;color:#222;line-height:20px;text-align:left;font-style:normal}.som[data-v-0471d126]{width:4px;height:22px;background:#00b0b0}.articles-container[data-v-0471d126]{display:flex}.articles-container .left[data-v-0471d126]{width:226px;height:226px;background:#ffffff;padding:30px 0;box-sizing:border-box}.articles-container .left .tong[data-v-0471d126]{font-family:PingFangSC,PingFang SC;font-weight:500;font-size:18px;color:#333;line-height:25px;text-align:left;font-style:normal;display:flex}.articles-container .right[data-v-0471d126]{margin-left:16px;width:850px;min-height:504px;background:#ffffff;padding:26px 24px}

Файловите разлики са ограничени, защото са твърде много
+ 0 - 0
dist/assets/edit.8e1f6c2e.css


Файловите разлики са ограничени, защото са твърде много
+ 0 - 0
dist/assets/inviteinfo.82fcb43f.css


BIN
dist/assets/logo.03d6d6da.png


+ 2 - 2
dist/index.html

@@ -6,8 +6,8 @@
   <link rel="icon" href="./favicon.ico" />
   <meta name="viewport" content="width=device-width, initial-scale=1.0" />
   <title>Vite App</title>
-  <script type="module" crossorigin src="./assets/index.67a4211c.js"></script>
-  <link rel="stylesheet" href="./assets/index.65f6f037.css">
+  <script type="module" crossorigin src="./assets/index.d8f1df7c.js"></script>
+  <link rel="stylesheet" href="./assets/index.eaddd9a7.css">
 </head>
 
 <body>

+ 1 - 1
src/api/private.js

@@ -22,5 +22,5 @@ export const chat = params => (request({
 export const multipart = data => (request({
     data,
     method: 'POST',
-    url: 'multipart/form-data'
+    url: 'chat'
 }))

+ 1 - 1
src/components/ActivateMembership/index.vue

@@ -130,7 +130,7 @@ const handleLogin = () => {
           <div class="title">开通权益</div>
           <ul>
             <li>购买额外赠送{{ info.integral||0 }}积分</li>
-            <li>开通赠送{{ info.coupon_count || 0 }}张优惠券</li>
+            <li>额外免费{{ info.coupon_count || 0 }}次拍摄</li>
             <li>升级领福利</li>
             <li>积分商城折扣</li>
           </ul>

+ 130 - 100
src/components/ChooseSubjectToTalk/index.vue

@@ -1,137 +1,154 @@
 <script setup>
-import { onMounted, reactive, ref } from "vue";
+import { onMounted, reactive, ref, watch } from "vue";
 import { CaretBottom, Search } from "@element-plus/icons-vue";
-import * as topticApi from '~/api/topic'
+import * as topticApi from "~/api/topic";
 import { ElMessage } from "element-plus";
-
+import { useRoute } from "vue-router";
 
 const Props = defineProps({
   line: {
     type: Boolean,
-    default: false
-  }
-})
-
-const Emits = defineEmits(['reciveTopic'])
-
+    default: false,
+  },
+  Topid: {
+    type: Number,
+  },
+  Title: {
+    Type: String,
+  },
+});
+
+const Emits = defineEmits(["reciveTopic"]);
+const leftShow = ref(true);
 // TODO: 缺少搜索项
-
+const route = useRoute();
 const visibleDialog = ref(false);
-const isSearch = ref(false)
-const keyword = ref('')
-
-const currentCategoryId = ref()
-const subjectList = ref([])
-const childrenList = ref([])
-
-
-const isFirst = ref(true) // 第一次会调用
+const isSearch = ref(false);
+const keyword = ref("");
+const confirmTopic = ref({});
+const currentCategoryId = ref();
+const subjectList = ref([]);
+const childrenList = ref([]);
+const isFirst = ref(true); // 第一次会调用
 const __topic_category__ = async () => {
   try {
-    const params = {
-    }
-    const { data } = await topticApi.category(params)
+    const params = {};
+    const { data } = await topticApi.category(params);
     if (data) {
       if (data.length && isFirst.value) {
-        isFirst.value = false
-        data[0].isSelected = true // 默认第一项选中
-        currentCategoryId.value = data[0].id
-        __topic_inlist__()
+        isFirst.value = false;
+        data[0].isSelected = true; // 默认第一项选中
+        currentCategoryId.value = data[0].id;
+        __topic_inlist__();
       }
-      subjectList.value = data || []
+      subjectList.value = data || [];
     }
-  } catch (error) {
-  }
-}
+  } catch (error) {}
+};
 const pagination = reactive({
   page: 1,
   limit: 10,
-})
+});
+
+
+watch(
+  () => Props.Topid,
+  (newVal) => {
+    currentCategoryId.value = newVal;
+    confirmTopic.value.title = Props.Title || "选择话题";
+  }
+);
+
+if (Props.Topid) {
+  currentCategoryId.value = Props.Topid;
+  confirmTopic.value.title = Props.Title || "选择话题";
+  console.log("confirmTopic", Props.Title);
+} else {
+  confirmTopic.value.title = "选择话题  ";
+}
 
-const __topic_inlist__ = async () => {
+const __topic_inlist__ = async (type) => {
   try {
     const params = {
       is_page: 1,
-      category_id: currentCategoryId.value,
+      category_id: type == 1 ? " " : currentCategoryId.value,
       title: keyword.value,
-      ...pagination
-    }
-    const { data } = await topticApi.list(params)
+      ...pagination,
+    };
+    const { data } = await topticApi.list(params);
     if (data) {
-      Loading.value = false
-      childrenList.value = data.list
-      if (data.page === data.last_page) { // 最后一页
-        isDisabledScroll.value = true
+      Loading.value = false;
+      childrenList.value = data.list;
+      if (data.page === data.last_page) {
+        // 最后一页
+        isDisabledScroll.value = true;
       }
     }
-  } catch (error) {
-
-  }
-}
+  } catch (error) {}
+};
 
-onMounted(__topic_category__)
+onMounted(__topic_category__);
 
 // 切换话题分类
 const handleChooseCategory = (category, idx) => {
-  if (currentCategoryId.value === category.id) return
+  if (currentCategoryId.value === category.id) return;
 
-  childrenList.value = []
-  Loading.value = true
-  currentCategoryId.value = category.id
+  childrenList.value = [];
+  Loading.value = true;
+  currentCategoryId.value = category.id;
 
   // reset pagination.
   Object.assign(pagination, {
     page: 1,
-    limit: 10
-  })
-
-  __topic_inlist__()
-}
+    limit: 10,
+  });
+  __topic_inlist__();
+};
 
 // 加载列表数据
-const Loading = ref(false)
-const isDisabledScroll = ref(false)
+const Loading = ref(false);
+const isDisabledScroll = ref(false);
 const handleLoadList = () => {
-  if (isDisabledScroll.value) return
-  Loading.value = true
+  if (isDisabledScroll.value) return;
+  Loading.value = true;
   // 加载下一页面
-  ++pagination.page
-  __topic_inlist__()
-}
+  ++pagination.page;
+  __topic_inlist__();
+};
 
 // 搜索模块
 const handleSearchConfirm = () => {
-  if (!keyword.value.length) return ElMessage.error('关键词为空不允搜索')
-  __topic_inlist__()
-}
+  if (!keyword.value.length) return ElMessage.error("关键词为空不允搜索");
+  __topic_inlist__(1);
+  leftShow.value = false;
+};
 
 // Clear keyword
 const handleClearEvent = () => {
-
   Object.assign(pagination, {
-    page: 1
-  })
-  __topic_inlist__()
-}
+    page: 1,
+  });
+  __topic_inlist__();
+};
 
 // 确认点击模块
-const confirmTopic = ref(null)
-const handleClickTopic = item => {
-  confirmTopic.value = item
+const handleClickTopic = (item) => {
+  confirmTopic.value = item;
   // 通过 emit 让知晓
-  Emits('reciveTopic', item)
-
-  visibleDialog.value = false
-}
-
+  Emits("reciveTopic", item);
+  visibleDialog.value = false;
+  leftShow.value = true;
+  keyword.value = "";
+};
 </script>
 
 <template>
   <div class="choose-subject-talk">
-    <el-button :class="[
-      Props.line ? 'noline' : ''
-    ]" @click="() => visibleDialog = !visibleDialog">
-      {{ confirmTopic ? confirmTopic.title : '选择话题' }}
+    <el-button
+      :class="[Props.line ? 'noline' : '']"
+      @click="() => (visibleDialog = !visibleDialog)"
+    >
+      {{ confirmTopic ? confirmTopic.title : "选择话题" }}
       <el-icon :size="22">
         <CaretBottom />
       </el-icon>
@@ -148,31 +165,44 @@ const handleClickTopic = item => {
               </el-icon>
             </template>
           </el-input>
-          <el-button type="primary" @click="handleSearchConfirm">搜索</el-button>
+          <el-button type="primary" @click="handleSearchConfirm"
+            >搜索</el-button
+          >
         </div>
         <div class="choose-subject flex-row flex-jc-sb">
           <!-- 搜索的话隐藏left块 -->
-          <div class="left">
+          <div class="left" v-if="leftShow">
             <ul>
-              <li v-for="(item, idx) in subjectList" :key="idx" :class="[
-                item.id === currentCategoryId ? 'active' : ''
-              ]" @click="handleChooseCategory(item, idx)">
+              <li
+                v-for="(item, idx) in subjectList"
+                :key="idx"
+                :class="[item.id === currentCategoryId ? 'active' : '']"
+                @click="handleChooseCategory(item, idx)"
+              >
                 <span>{{ item.name }}</span>
               </li>
             </ul>
           </div>
           <div class="right">
-            <ul v-infinite-scroll="handleLoadList" :infinite-scroll-distance="20"
-              :infinite-scroll-disabled="isDisabledScroll" :infinite-scroll-immediate="false"
-              v-if="Loading || isSearch || childrenList.length" class="scroll-optimize">
-              <li v-for="(item, idx) in childrenList" :key="idx" @click="handleClickTopic(item)"><span>{{ item.title
-              }}</span></li>
+            <ul
+              v-infinite-scroll="handleLoadList"
+              :infinite-scroll-distance="20"
+              :infinite-scroll-disabled="isDisabledScroll"
+              :infinite-scroll-immediate="false"
+              v-if="Loading || isSearch || childrenList.length"
+              class="scroll-optimize"
+            >
+              <li
+                v-for="(item, idx) in childrenList"
+                :key="idx"
+                @click="handleClickTopic(item)"
+              >
+                <span>{{ item.title }}</span>
+              </li>
               <li v-if="Loading">加载中...</li>
               <li v-if="isSearch" class="tips">已加载全部</li>
             </ul>
-            <div class="empty" v-else>
-              没有内容
-            </div>
+            <div class="empty" v-else>没有内容</div>
           </div>
         </div>
       </div>
@@ -204,12 +234,12 @@ const handleClickTopic = item => {
 
   .search-wrapper {
     padding: 10px 6px;
-    background: #F5F5F5;
+    background: #f5f5f5;
     column-gap: 10px;
     border-radius: 6px;
 
     :deep(.el-input__wrapper:hover) {
-      box-shadow: initial
+      box-shadow: initial;
     }
   }
 
@@ -226,7 +256,7 @@ const handleClickTopic = item => {
     .left {
       width: 130px;
       // background-color: #fff;
-      background: #F5F5F5;
+      background: #f5f5f5;
       // max-height: 60px; /** 需要最大高度固定 */
       overflow: auto;
 
@@ -241,7 +271,7 @@ const handleClickTopic = item => {
       }
 
       &::-webkit-scrollbar-thumb:hover {
-        background: #A0A0A0;
+        background: #a0a0a0;
       }
 
       li {
@@ -278,7 +308,7 @@ const handleClickTopic = item => {
         font-size: 16px;
         font-weight: 500;
         color: #333333;
-        border-bottom: 1px solid #F5F5F5;
+        border-bottom: 1px solid #f5f5f5;
         cursor: pointer;
 
         &:last-child {
@@ -290,7 +320,7 @@ const handleClickTopic = item => {
         text-align: center;
         font-size: 16px;
         font-weight: 400;
-        color: rgba(51, 51, 51, .6);
+        color: rgba(51, 51, 51, 0.6);
       }
 
       .empty {

+ 28 - 6
src/components/Comments/index.vue

@@ -48,7 +48,7 @@ const replace1 = async () => {
       content: textarea.value,
     });
     textarea.value = "";
-    __list__()
+    __list__(parent_id);
   } catch (error) {}
 };
 
@@ -65,6 +65,22 @@ const __list__ = async () => {
     commentList.value = data.slice(0, 5);
   } catch (error) {}
 };
+const __childList__ = async (parent_id) => {
+  try {
+    const { data } = await commentApi.list({
+      source_type: source_type.value,
+      source_id: Props.id,
+      order_type: "desc",
+      order: currentCommentType.value == "hot" ? "like_count" : "id",
+      top_parent_id: parent_id,
+    });
+    commentList.value.forEach((item) => {
+      if (item.id == parent_id) {
+        item.children = data;
+      }
+    });
+  } catch (error) {}
+};
 const showa = ref(true);
 const tomore = async () => {
   try {
@@ -87,9 +103,10 @@ watch(currentCommentType, () => {
 const end = ref(2);
 const childshow = ref(true);
 //更多
-const childmore = (num) => {
+const childmore = (parent_id, num) => {
   end.value = num;
   childshow.value = ref(false);
+  __childList__(parent_id);
 };
 
 const change = (type) => {
@@ -147,10 +164,12 @@ const change = (type) => {
             :parent_id="item.id"
             :source_id="Props.id"
             :crateTime="item.created_at"
+            :is_like="item.is_like"
+            :avatar="item.user.avatar"
             @list="__list__"
           />
         </dt>
-        <dd v-for="(child, index) in item.children.slice(0, end)" :key="index">
+        <dd v-for="(child, index) in item.children" :key="index">
           <CommentRow
             :source_type="source_type"
             :crateTime="child.created_at"
@@ -161,12 +180,15 @@ const change = (type) => {
             :comment_count="child.comment_count"
             :parent_id="child.id"
             :source_id="Props.id"
+            :is_like="child.is_like"
+            :avatar="child.user.avatar"
+            @list="__list__"
           />
         </dd>
-        <dd v-if="item.children.length > 3 && childshow == true">
+        <dd v-if="item.children.length <= 2 && item.children.length != 0">
           <span
             class="comment-list-more"
-            @click="childmore(item.children.length)"
+            @click="childmore(item.children[0].parent_id, item.children.length)"
           >
             查看全部回复<el-icon>
               <ArrowDown></ArrowDown>
@@ -176,7 +198,7 @@ const change = (type) => {
       </dl>
     </div>
     <!-- TODO: see more -->
-    <div v-if="commentList.length > 4 && showa == true" class="comment-morebox">
+    <div v-if="commentList.length > 2 && showa == true" class="comment-morebox">
       <span style="cursor: pointer" @click="tomore">更多评论</span>
     </div>
   </div>

+ 41 - 8
src/components/Comments/row.vue

@@ -4,6 +4,7 @@ import { computed, ref } from "vue";
 import { placeholderPic } from "~/utils/util";
 //评论接口
 import * as commentApi from "~/api/comment";
+import * as gatherApi from "~/api/gather";
 
 const Props = defineProps({
   name: {
@@ -41,6 +42,12 @@ const Props = defineProps({
     type: String,
     default: "",
   },
+  is_like: {
+    type: Number,
+  },
+  avatar:{
+    type:String
+  }
 });
 
 // 是否有回复
@@ -50,7 +57,7 @@ const replace = () => {
   dialogVisible.value = true;
 };
 //回复
-const emit = defineEmits(["todetails"]);
+const emit = defineEmits(["todetails"], ["like"]);
 const todetails = () => {
   emit("list");
 };
@@ -67,30 +74,56 @@ const replace1 = async () => {
     todetails();
   } catch (error) {}
 };
+//点赞
+const like = async (id) => {
+  try {
+    const { msg } = await gatherApi.like({
+      source_type: "comment",
+      source_id: Props.parent_id,
+    });
+    ElMessage({
+      message: msg,
+      type: "success",
+    });
+    todetails();
+  } catch (error) {
+    console.log("error", error);
+  }
+};
 </script>
 
 <template>
   <div class="comment-row-container flex-row">
     <div class="comment-row-avatar">
-      <img class="circle" :src="placeholderPic(44, 44)" alt="" />
+      <img class="circle" :src="Props.avatar" style="width: 40px;height: 40px;" alt="" />
     </div>
     <div class="comment-row-main">
       <div class="comment-row-main__header flex-row flex-aic">
         <div class="namebox flex-row flex-aic">
-          <a href="javascript:void(0);" class="crcuname">{{ name }}</a>
+          <span  class="crcuname">{{ name }}</span>
           <template v-if="existReply">
             <span>回复</span>
-            <a href="javascript:void(0);" class="crconame">{{ reply }}</a>
+            <a  class="crconame">{{ reply }}</a>
           </template>
         </div>
         <div class="timebox">· {{ Props.crateTime }}</div>
       </div>
       <p class="comment-row-main__descs">{{ descs }}</p>
       <ul class="comment-row-main__footer flex-row">
-        <li>
-          <SvgIcon name="like" :size="22" :rgap="2" color="#888888" />
-          <span>赞</span>
-          <span>{{ Props.like_count }}</span>
+        <li @click="like(Props.id)">
+          <SvgIcon
+            name="like"
+            :size="22"
+            :rgap="2"
+            :color="Props.is_like == 1 ? '#00b0b0' : '#999999'"
+          />
+          <span :style="{ color: Props.is_like == 1 ? '#00b0b0' : '#999999' }"
+            >赞</span
+          >
+          <span
+            :style="{ color: Props.is_like == 1 ? '#00b0b0' : '#999999' }"
+            >{{ Props.like_count }}</span
+          >
         </li>
         <li @click="replace">
           <SvgIcon name="message" :size="22" :rgap="2" color="#888888" />

+ 72 - 3
src/components/IndexSection/index.vue

@@ -4,6 +4,7 @@ import SvgIcon from "~/components/SvgIcon/index.vue";
 import { useUser } from "~/store/user";
 import * as formatTime from "~/utils/formatTime";
 import * as gatherApi from "~/api/gather";
+import { ref } from "vue";
 
 const handleTimeAgo = formatTime.timeAgo;
 const Props = defineProps({
@@ -82,11 +83,68 @@ const collect = async () => {
     });
   } catch (error) {}
 };
-
-const shareLink = () => {};
+//分享
+const dialogVisible = ref(false);
+const url = ref();
+const share = () => {
+  dialogVisible.value = true;
+  if (Props.source_type == "article") {
+    url.value =
+      "https://vr.hdlkeji.com/web/#/article?" + "id=" + Props.source_id;
+  } else {
+    url.value =
+      "https://vr.hdlkeji.com/web/#/videos?" +
+      "id=" +
+      Props.source_id +
+      "&type=" +
+      "common";
+  }
+};
+const shareLink = async () => {
+  try {
+    await navigator.clipboard.writeText(url.value);
+    alert("链接已复制到剪贴板");
+    __share__();
+  } catch (err) {
+    alert("复制链接失败");
+  }
+};
+const __share__ = async () => {
+  try {
+    const { data } = await gatherApi.share({
+      source_type: Props.source_type,
+      source_id: Props.source_id,
+    });
+    emit("video");
+    emit("article");
+  } catch (error) {}
+};
 </script>
 
 <template>
+  <el-dialog title="分享" v-model="dialogVisible" width="500px">
+    <div style="display: flex">
+      <input
+        disabled
+        v-model="url"
+        style="
+          width: 400px;
+          height: 44px;
+          box-sizing: border-box;
+          background: #f5f5f5;
+          border: 0 solid rgba(0, 0, 0, 0);
+          padding-left: 20px;
+        "
+      />
+      <div class="back" @click="shareLink">
+        <img
+          src="../../assets/link.png"
+          style="width: 18px; height: 18px"
+          alt=""
+        />
+      </div>
+    </div>
+  </el-dialog>
   <div class="index-section-container">
     <div @click="todetails" v-if="type === 'common'" class="imgbox">
       <img
@@ -150,7 +208,7 @@ const shareLink = () => {};
             <SvgIcon name="message" :size="16" :rgap="2" color="#999999" />
             <span>{{ Props.comment_count || 0 }}</span>
           </li>
-          <li>
+          <li @click="share">
             <SvgIcon name="forward" :size="16" :rgap="2" color="#999999" />
             <span>{{ Props.share_count || 0 }}</span>
           </li>
@@ -161,6 +219,17 @@ const shareLink = () => {};
 </template>
 
 <style lang="scss" scoped>
+.back {
+  width: 50px;
+  height: 44px;
+  background: #00b0b0;
+  border-radius: 0px 4px 4px 0px;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+  cursor: pointer;
+}
 .index-section {
   &-container {
     width: 275px;

+ 11 - 2
src/components/IndexTitle/index.vue

@@ -10,14 +10,23 @@ const Props = defineProps({
 
 const Emits = defineEmits(["seeMore"]);
 const seeMore = () => {
-  Emits("seeMore",Props.title);
+  Emits("seeMore", Props.title);
 };
 </script>
 
 <template>
   <div class="index-title-container flex-row flex-aic flex-jc-sb">
     <div class="title">{{ title }}</div>
-    <div v-if="title=='精选视频'||title=='精选文章'||title=='精选资讯'" class="more flex-row flex-aic" @click="seeMore()">
+    <div
+      v-if="
+        title == '精选视频' ||
+        title == '精选文章' ||
+        title == '精选资讯' ||
+        title == '大家在聊'
+      "
+      class="more flex-row flex-aic"
+      @click="seeMore()"
+    >
       <span>查看更多</span>
       <el-icon class="icon" :size="12">
         <ArrowRight />

+ 1 - 1
src/components/MomentLayout/com.vue

@@ -18,7 +18,7 @@ const Props = defineProps({
   <div class="moment-layout-com-container">
     <div class="cover-image" v-if="Props.image">
       <!-- placeholderPic(600, 300) -->
-      <img :src="Props.image" alt="">
+      <img style="width: 100%;" :src="Props.image" alt="">
     </div>
     <h3 class="title">{{ Props.title }}</h3>
     <p class="content">

+ 105 - 23
src/components/MomentLayout/index.vue

@@ -16,8 +16,15 @@ import { useUserOperate } from "~/useHook/useUserOperate";
 import { useTools } from "~/useHook/useTools";
 import { ElMessage } from "element-plus";
 import { useUser } from "~/store/user";
+import {
+  ArrowLeft,
+  LocationFilled,
+  WarningFilled,
+  SuccessFilled,
+} from "@element-plus/icons-vue";
 const User = useUser();
 const { getSvgCol } = useTools();
+const delectshow = ref(false);
 
 const {
   __operate_link__,
@@ -80,7 +87,7 @@ const detail = () => {
 };
 const delec = () => {
   Emits("delec");
-  console.log("111");
+  delectshow.value = false;
 };
 </script>
 
@@ -122,13 +129,34 @@ const delec = () => {
             </template>
             <div class="more__main">
               <ul style="cursor: pointer">
-                <li v-if="Author.id == User.id" @click="delec">删除</li>
+                <li v-if="Author.id == User.id" @click="delectshow = true">
+                  删除
+                </li>
                 <li v-else @click="handleReportError">举报</li>
               </ul>
             </div>
           </el-popover>
         </div>
       </div>
+      <el-dialog v-model="delectshow" width="354">
+        <div
+          style="
+            display: flex;
+            flex-direction: column;
+            justify-content: center;
+            align-items: center;
+          "
+        >
+          <el-icon color="rgba(246, 177, 19, 1)" :size="34" class="no-inherit">
+            <WarningFilled />
+          </el-icon>
+          <div style="margin-top: 16px" class="changeadd">确定要删除吗?</div>
+          <div style="display: flex; margin-top: 26px">
+            <div class="cancel" @click="delectshow = false">取消</div>
+            <div class="confirm" @click="delec">确定</div>
+          </div>
+        </div>
+      </el-dialog>
     </div>
 
     <!-- main -->
@@ -141,20 +169,20 @@ const delec = () => {
         视频内容
         论坛内容 PS: 可以多图
        -->
-      <template v-if="['article', 'news', 'info'].includes(Props.type)">
+      <!-- :introduction="
+            Props.detail.content || Props.detail.source.content
+          " -->
+      <template v-if="['article', 'news'].includes(Props.type) && Props.detail">
         <component
+          v-if="Props.detail"
           :is="Common"
           :image="Props.detail.image || Props.detail.source.image"
           :title="Props.detail.title || Props.detail.source.title"
-          :introduction="
-            Props.detail.description
-              ? Props.detail.description
-              : Props.detail.source.description
-          "
         />
       </template>
-      <template v-else-if="Props.type === 'video'">
+      <template v-else-if="Props.type === 'video' && Props.detail">
         <component
+          v-if="Props.detail"
           :is="videoContent"
           :image="Props.detail.image || Props.detail.source.image"
           :video-title="
@@ -166,16 +194,8 @@ const delec = () => {
       <template v-else>
         <component
           :is="forumContent"
-          :images="
-            Props.detail.images
-              ? Props.detail.images
-              : Props.detail.source.images
-          "
-          :content="
-            Props.detail.content
-              ? Props.detail.content
-              : Props.detail.source.content
-          "
+          :images="Props.detail.images || Props.detail.source.images"
+          :content="Props.detail.content || Props.detail.source.content"
         />
       </template>
     </div>
@@ -193,7 +213,9 @@ const delec = () => {
     <div class="footer flex-row flex-aic flex-jc-sb">
       <div class="l">
         <span
-          :style="{ color: Props.detail.is_like == 1 ? '#00b0b0' : '#999999' }"
+          :style="{
+            color: Props.detail.is_like == 1 ? '#00b0b0' : 'rgb(102, 102, 102)',
+          }"
           class="btn like"
           @click="handleOperate('like')"
           v-if="Props.detail"
@@ -201,7 +223,9 @@ const delec = () => {
           <SvgIcon
             name="like"
             :size="20"
-            :color="Props.detail.is_like == 1 ? '#00b0b0' : '#999999'"
+            :color="
+              Props.detail.is_like == 1 ? '#00b0b0' : 'rgb(102, 102, 102)'
+            "
           />
           {{
             Props.detail.like_count ||
@@ -211,7 +235,8 @@ const delec = () => {
         <span
           key=""
           :style="{
-            color: Props.detail.is_collect == 1 ? '#00b0b0' : '#999999',
+            color:
+              Props.detail.is_collect == 1 ? '#00b0b0' : 'rgb(102, 102, 102)',
           }"
           class="btn collect"
           @click="handleOperate('collect')"
@@ -220,7 +245,9 @@ const delec = () => {
           <SvgIcon
             name="collect"
             :size="20"
-            :color="Props.detail.is_collect == 1 ? '#00b0b0' : '#999999'"
+            :color="
+              Props.detail.is_collect == 1 ? '#00b0b0' : 'rgb(102, 102, 102)'
+            "
           />
           {{
             Props.detail.collect_count ||
@@ -261,6 +288,61 @@ const delec = () => {
 </template>
 
 <style lang="scss">
+.confirm {
+  width: 78px;
+  height: 36px;
+  background: #00b0b0;
+  border-radius: 4px;
+  font-family: PingFangSC, PingFang SC;
+  font-weight: 400;
+  font-size: 14px;
+  color: #ffffff;
+  font-style: normal;
+  margin-left: 22px;
+  line-height: 36px;
+  text-align: center;
+  cursor: pointer;
+}
+.cancel {
+  width: 78px;
+  height: 36px;
+  background: #c5c5c5;
+  border-radius: 4px;
+  text-align: center;
+  line-height: 36px;
+  font-family: PingFangSC, PingFang SC;
+  font-weight: 400;
+  font-size: 14px;
+  color: #ffffff;
+  font-style: normal;
+  cursor: pointer;
+}
+.compile {
+  width: 66px;
+  height: 36px;
+  background: #00b0b0;
+  border-radius: 4px;
+  font-family: PingFangSC, PingFang SC;
+  font-weight: 400;
+  font-size: 14px;
+  color: #ffffff;
+  line-height: 36px;
+  text-align: center;
+  font-style: normal;
+}
+.dele {
+  width: 66px;
+  height: 36px;
+  background: #eb3939;
+  border-radius: 4px;
+  font-family: PingFangSC, PingFang SC;
+  font-weight: 400;
+  font-size: 14px;
+  color: #ffffff;
+  line-height: 36px;
+  text-align: center;
+  font-style: normal;
+}
 // 当前为全局变量。
 .el-popover.el-popper.popover-imore {
   min-width: 70px !important;

+ 21 - 2
src/components/UserCard/index.vue

@@ -4,6 +4,8 @@ import { useRouter } from "vue-router";
 import { EditPen, Promotion } from "@element-plus/icons-vue";
 import * as user from "~/api/user";
 import { placeholderPic } from "~/utils/util";
+import router from "~/router";
+
 
 const Router = useRouter();
 
@@ -18,6 +20,23 @@ const Prope = defineProps({
     default: () => ({}),
   },
 });
+//编辑
+const toinfo = ()=>{
+  Router.push({
+    path:'/setting'
+  })
+}
+
+//私信
+const tochat = (id)=>{
+  Router.push({
+    path:'chat',
+    query:{
+      id:id,
+      username:Prope.detail.username
+    }
+  })
+}
 
 let followingTxt = computed(() =>
   Prope.type === "myself" ? "我关注" : "已关注"
@@ -76,7 +95,7 @@ const change = () => {
           src="../../assets/bage/icon3.png"
         />
       </div>
-      <el-icon v-if="type === 'myself'" :size="18">
+      <el-icon @click="toinfo" style="cursor: pointer;" v-if="type === 'myself'" :size="18">
         <EditPen></EditPen>
       </el-icon>
     </div>
@@ -143,7 +162,7 @@ const change = () => {
           @click="about(Prope.detail.id)"
           >已关注</el-button
         >
-        <el-button size="large">私信</el-button>
+        <el-button size="large" @click="tochat(Prope.detail.id)">私信</el-button>
       </div>
     </template>
 

+ 82 - 12
src/components/layouts/Header.vue

@@ -71,6 +71,7 @@ const __fans__ = async () => {
       is_page: 0,
     });
     fllowlist.value = data;
+    User.getUser();
   } catch (error) {}
 };
 //粉丝列表
@@ -80,20 +81,61 @@ const __article__ = async () => {
       is_page: 0,
     });
     fllowlist.value = data;
+    User.getUser();
   } catch (error) {}
 };
 onMounted(__article__);
 
+// const tosuccess = (type) => {
+//   if (type == "browse") {
+//     router.replace({
+//       name: "Forum",
+//     });
+//   } else if (type == "share_post") {
+//     router.replace({
+//       name: "Articles",
+//     });
+//   }
+// };
+
+//任务跳转
 const tosuccess = (type) => {
+  if (type == "like") {
+    router.push({
+      path: "/articles",
+    });
+  }
   if (type == "browse") {
-    router.replace({
-      name: "Forum",
+    router.push({
+      path: "/forum",
     });
-  } else if (type == "share_post") {
-    router.replace({
-      name: "Articles",
+  }
+  if (type == "create_post") {
+    router.push({
+      path: "/forum",
+    });
+  }
+  if (type == "invite") {
+    router.push({
+      path: "/setting",
+      query: {
+        subNavCurrent: "invite",
+      },
     });
   }
+  if (type == "share_post") {
+    router.push({
+      path: "/articles",
+    });
+  }
+  if (type == "finish_info") {
+    router.push({
+      path: "/setting",
+    });
+  }
+  if (type == "vip") {
+    pan.value = true;
+  }
 };
 
 // 弹出层
@@ -102,7 +144,13 @@ const dialogs = ref(false);
 const clearLocalStorage = () => {
   localStorage.clear();
   dialogs.value = false;
-  router.go(0);
+  router
+    .push({
+      path: "/",
+    })
+    .then(() => {
+      location.reload();
+    });
 };
 //跳转到个人信息
 const topersonal = () => {
@@ -122,6 +170,19 @@ const __task__ = async () => {
     taskList.value = data.reverse();
   } catch (error) {}
 };
+//任务列表领取奖励
+const togetb = async (id) => {
+  try {
+    const { data } = await taskApi.task({
+      id: id,
+    });
+    ElMessage({
+      message: "领取成功",
+      type: "success",
+    });
+    __task__();
+  } catch (error) {}
+};
 onMounted(__task__);
 const imglist = ref();
 const __badge__ = async () => {
@@ -256,17 +317,16 @@ const userRankList = () => {
 onMounted(userRankList);
 
 const handleClickMoment = (moment) => {
-  if (moment.type == "forum") {
-    router.push({
-      path: "/forum",
-    });
-  } else if (moment.type == "drafts") {
+  if (moment.type == "drafts") {
     router.push({
       path: "/draft",
     });
   } else {
     router.push({
       path: "/editor",
+      query: {
+        type: moment.type,
+      },
     });
   }
 };
@@ -513,7 +573,10 @@ const attention = (idx) => {
                   alt=""
                 />
               </div>
-              <div class="uc__integral flex-row flex-aic flex-jc-sb">
+              <div
+                style="margin-top: 20px"
+                class="uc__integral flex-row flex-aic flex-jc-sb"
+              >
                 <span class="integral_text"
                   >当前积分{{ User.integral_sum }},差{{
                     User.left_upgrade
@@ -571,6 +634,13 @@ const attention = (idx) => {
                             >
                               去完成
                             </div>
+                            <div
+                              class="success"
+                              v-else-if="item.status == 'finished'"
+                              @click="togetb(item.id)"
+                            >
+                              领取奖励
+                            </div>
                             <div class="success" v-else>已完成</div>
                           </div>
                         </el-dropdown-item>

+ 15 - 7
src/components/layouts/HeaderEditor.vue

@@ -1,6 +1,6 @@
 <script setup>
 import { ref, watch } from "vue";
-import { useRouter } from "vue-router";
+import { useRouter,useRoute } from "vue-router";
 import { useUser } from "~/store/user.js";
 import { useCommonStore } from "~/store/index.js";
 import ActivateMembership from "~/components/ActivateMembership/index.vue";
@@ -8,7 +8,7 @@ import ActivateMembership from "~/components/ActivateMembership/index.vue";
 const User = useUser();
 const Common = useCommonStore();
 const Router = useRouter();
-
+const route = useRoute()
 const options = ref([
   { label: "文章", value: "article" },
   { label: "资讯", value: "news" },
@@ -17,13 +17,21 @@ const options = ref([
 ]);
 
 const value = ref("article"); // default article
-
+if(route.query.type=='info'){
+  value.value = 'news'
+}else if(route.query.type=='article'){
+  value.value = 'article'
+}else if(route.query.type=='video'){
+  value.value = 'video'
+}else{
+  value.value = 'forum'
+}
 //跳转到个人中心
-const toinfo = ()=>{
+const toinfo = () => {
   Router.push({
-    path:'personal'
-  })
-}
+    path: "personal",
+  });
+};
 
 watch(
   () => value.value,

+ 0 - 1
src/components/layouts/LayoutEditor.vue

@@ -6,7 +6,6 @@ import { useRoute } from "vue-router";
 const route = useRoute();
 const key = computed(() => route.path + Math.random());
 </script>
-
 <template>
   <div class="container">
     <el-container>

+ 0 - 1
src/components/layouts/LayoutHeader.vue

@@ -17,7 +17,6 @@ const key = computed(() => route.path + Math.random());
         <div class="layout-container">
           <router-view v-slot="{ Component }" :key="'key'">
             <transition name="move" mode="out-in">
-              <!-- NOTE: <keep-alive></keep-alive> -->
               <component :is="Component"></component>
             </transition>
           </router-view>

+ 1 - 1
src/router/index.js

@@ -60,7 +60,7 @@ const routes = [
         component: () => import('~/views/articles/index.vue')
       },
       {
-        path: '/Articles',
+        path: '/article',
         name: 'articles',
         component: () => import('~/views/postDetail.vue')
       },

+ 2 - 1
src/useHook/useForum.js

@@ -25,7 +25,8 @@ export function useForumIndex() {
     status: 'normal',
     is_boutique: 0,
     order: 'id',
-    order_type: 'desc'
+    order_type: 'desc',
+    
   })
 
   const forumType = ref('latest') // latest: 最新, comment: 评论, upvote: 点赞 

+ 1 - 1
src/utils/constance.js

@@ -57,7 +57,7 @@ export const PERSONAL_SECOND_SUB_NAV_LIST = [
   },
   {
     label: "商品",
-    value: "goods"
+    value: "integral_goods"
   }
 ]
 

+ 184 - 102
src/views/forum/edit.vue

@@ -5,140 +5,158 @@ import { useRouter, useRoute } from "vue-router";
 
 import ChooseSubjectToTalk from "~/components/ChooseSubjectToTalk/index.vue";
 import { getSourcesSuffix } from "~/utils/util";
-import { useUploadImage } from "~/useHook/useUploadImage"
+import { useUploadImage } from "~/useHook/useUploadImage";
 import { usePost } from "~/useHook/usePost";
 
 import draggable from "vuedraggable";
 
-const IMAGE_SUFFIX = getSourcesSuffix('image')
-const Router = useRouter()
-const Route = useRoute()
+const IMAGE_SUFFIX = getSourcesSuffix("image");
+const Router = useRouter();
+const Route = useRoute();
 
-const editId = Route.query?.id
+const editId = Route.query?.id;
+const currentTopid = ref()
+const topicTitle = ref()
+currentTopid.value = Route.query.id;
+topicTitle.value = Route.query.title;
 
-console.log('%c editId >>>', 'background: blue; color: #fff', editId);
+console.log("%c editId >>>", "background: blue; color: #fff", editId);
 
+const forumDesc = ref("");
 
-const forumDesc = ref('')
-
-const handleRecordMoment = status => {
+const handleRecordMoment = (status) => {
   // status: draft.草稿, normal.发布
-  let str = status === 'draft' ? '存草稿' : '发布'
+  let str = status === "draft" ? "存草稿" : "发布";
 
   ElMessageBox.confirm(`确认要${str}吗`).then(async () => {
     let formdata = {
       content: forumDesc.value,
-      topic_id: currentTopic.value ? currentTopic.value.id : '0', // default 0 or ''
+      topic_id: currentTopic.value ? currentTopic.value.id : "0", // default 0 or ''
       status: status,
-      images: showFileList.value.map(image => (image.urlHref))
-    }
+      images: showFileList.value.map((image) => image.urlHref),
+    };
     try {
-      const result = await usePost('forum', formdata)
-      ElMessage.success(`${str}成功`)
+      const result = await usePost("forum", formdata);
+      ElMessage.success(`${str}成功`);
+      if (str == "存草稿") {
+        Router.push({
+          path: "/draft",
+        });
+      } else if (str == "发布") {
+        Router.push({
+          path: "/forum",
+        });
+      }
     } catch (error) {
-      ElMessage.error(`${str}失败`)
+      ElMessage.error(`${str}失败`);
     }
-  })
-}
+  });
+};
 
-const visibilityDialog = ref(false)
+const visibilityDialog = ref(false);
 
 // TODO:取消发布是否要主动吊起存草稿状态
 const handleCancelSend = () => {
-  Router.back()
-}
+  Router.back();
+};
 
 // 接收话题
-const currentTopic = ref(null)
-const handleReciveTopic = topic => {
-  console.log('%c current topic >>>', 'background: blue; color: #fff', topic);
-  currentTopic.value = topic
-}
+const currentTopic = ref(null);
+const handleReciveTopic = (topic) => {
+  console.log("%c current topic >>>", "background: blue; color: #fff", topic);
+  currentTopic.value = topic;
+};
 
 // upload file
-const uploadRef = ref()
-const fileList = ref([])
+const uploadRef = ref();
+const fileList = ref([]);
 const handleClickUploadBtn = () => {
-  visibilityDialog.value = true
-}
+  visibilityDialog.value = true;
+};
 
 // remove image
-const handleRemoveImage = element => {
-  fileList.value.splice(fileList.value.findIndex(file => file === element), 1)
-  fileList.value = fileList.value.filter(file => file !== element)
-}
-
-const visibilityImagePreview = ref(false)
-const imagePreviewUrl = ref('')
-const handlePictureCardPreviewImage = element => {
-  visibilityImagePreview.value = false
-  imagePreviewUrl.value = element.url
-  visibilityImagePreview.value = true
-}
-
-// TODO: 上传多图的 loading 
+const handleRemoveImage = (element) => {
+  fileList.value.splice(
+    fileList.value.findIndex((file) => file === element),
+    1
+  );
+  fileList.value = fileList.value.filter((file) => file !== element);
+};
+
+const visibilityImagePreview = ref(false);
+const imagePreviewUrl = ref("");
+const handlePictureCardPreviewImage = (element) => {
+  visibilityImagePreview.value = false;
+  imagePreviewUrl.value = element.url;
+  visibilityImagePreview.value = true;
+};
+
+// TODO: 上传多图的 loading
 // 辅助上传图片
-const handleUploadImage = async options => {
-  console.log('%c options >>>', 'background: blue; color: #fff', options);
+const handleUploadImage = async (options) => {
+  console.log("%c options >>>", "background: blue; color: #fff", options);
   try {
+    const { file } = options;
 
-    const { file } = options
-
-    const formdata = new FormData()
+    const formdata = new FormData();
 
-    formdata.append('image', file)
+    formdata.append("image", file);
 
-    const { imageFile } = await useUploadImage(formdata)
-    console.log('%c ImageFile >>>', 'background: blue; color: #fff', imageFile);
+    const { imageFile } = await useUploadImage(formdata);
+    console.log("%c ImageFile >>>", "background: blue; color: #fff", imageFile);
     // imageCover.value = imageFile.value
-    options.onSuccess(imageFile.value)
-    console.log('show val>>>', fileList.value);
+    options.onSuccess(imageFile.value);
+    console.log("show val>>>", fileList.value);
   } catch (error) {
-    options.onError(options.file)
-    console.log('%c ??? >>>', 'background: blue; color: #fff', error);
-    ElMessage.error('上传封面图出错')
+    options.onError(options.file);
+    console.log("%c ??? >>>", "background: blue; color: #fff", error);
+    ElMessage.error("上传封面图出错");
   }
-}
+};
 
 // upload image success event;
 const handleUploadImageSuccess = (response, uploadFile) => {
   if (response) {
-    uploadFile.urlHref = response
+    uploadFile.urlHref = response;
   }
-}
+};
 
 // 图片上传失败。
 // TODO: 根据上传失败的图片 `uid`进行判断是否删除列表失败图片
 const handleUploadImageError = (file, uploadFile) => {
   if (file) {
-    console.log('error', file);
-    const { uid } = uploadFile
+    console.log("error", file);
+    const { uid } = uploadFile;
     // TODO: 更新fileList
     // handleConfirmImagesShow()
-
   }
-}
+};
 
 // 确定文件列表可以被展示
-const showFileList = ref([]) // 用于展示的图片列表
+const showFileList = ref([]); // 用于展示的图片列表
 const handleConfirmImagesShow = () => {
   if (!fileList.value.length) return;
-  let temporaryArrs = []
-  fileList.value.map(file => {
-    console.log('%c file == >>>', 'background: blue; color: #fff', file);
-    temporaryArrs.push(file)
-  })
-  showFileList.value = [...temporaryArrs]
-  visibilityDialog.value = false
-}
-
+  let temporaryArrs = [];
+  fileList.value.map((file) => {
+    console.log("%c file == >>>", "background: blue; color: #fff", file);
+    temporaryArrs.push(file);
+  });
+  showFileList.value = [...temporaryArrs];
+  visibilityDialog.value = false;
+};
 </script>
 
 <template>
   <div class="forum-edit-container">
     <div class="header flex-row flex-aic flex-jc-sb">
       <div class="title">论坛话题发布</div>
-      <div class="cancel" @click="handleCancelSend">取消发布</div>
+      <div
+        class="cancel"
+        style="background-color: #fff"
+        @click="handleCancelSend"
+      >
+        取消发布
+      </div>
     </div>
 
     <div class="forum-edit-upload">
@@ -157,28 +175,61 @@ const handleConfirmImagesShow = () => {
       </div>
     </div>
 
-    <el-input resize="none" :show-word-limit="true" placeholder="请输入你想发布的内容..." type="textarea" :rows="12"
-      v-model="forumDesc"></el-input>
+    <el-input
+      resize="none"
+      :show-word-limit="true"
+      placeholder="请输入你想发布的内容..."
+      type="textarea"
+      :rows="12"
+      v-model="forumDesc"
+    ></el-input>
 
     <footer class="footer flex-row flex-aic flex-jc-sb">
       <div class="footer__left">
-        <ChooseSubjectToTalk line @recive-topic="handleReciveTopic" />
+        <ChooseSubjectToTalk
+          line
+          @recive-topic="handleReciveTopic"
+          :Topid="currentTopid"
+          :Title="topicTitle"
+        />
       </div>
       <div class="footer__right">
         <el-button @click="handleRecordMoment('draft')">存草稿</el-button>
-        <el-button type="primary" @click="handleRecordMoment('normal')">发布</el-button>
+        <el-button type="primary" @click="handleRecordMoment('normal')"
+          >发布</el-button
+        >
       </div>
     </footer>
 
-    <el-dialog class="dialog-uploadbox" title="图库编辑" v-model="visibilityDialog" width="560">
+    <el-dialog
+      class="dialog-uploadbox"
+      title="图库编辑"
+      v-model="visibilityDialog"
+      width="560"
+    >
       <p class="tips">选择图片并排序,最多不超过9张</p>
       <div class="dialog-mainbox">
-        <draggable class="custom-draggable" filter=".unmove" :list="fileList" ghost-class="ghost"
-          chosen-class="chosenClass" animation="200" :sort="true" item-key="element">
+        <draggable
+          class="custom-draggable"
+          filter=".unmove"
+          :list="fileList"
+          ghost-class="ghost"
+          chosen-class="chosenClass"
+          animation="200"
+          :sort="true"
+          item-key="element"
+        >
           <template #item="{ element }">
-            <ul :item-key="element" class="el-upload-list el-upload-list--picture-card">
-              <li class="el-upload-list__item is-success  animated">
-                <img :src="element.url" alt="" class="el-upload-list__item-thumbnail ">
+            <ul
+              :item-key="element"
+              class="el-upload-list el-upload-list--picture-card"
+            >
+              <li class="el-upload-list__item is-success animated">
+                <img
+                  :src="element.url"
+                  alt=""
+                  class="el-upload-list__item-thumbnail"
+                />
                 <!-- <label class="el-upload-list__item-status-label">
                   <i class="el-icon el-icon--upload-success  el-icon--check">
                     <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024">
@@ -190,22 +241,36 @@ const handleConfirmImagesShow = () => {
                 </label> -->
                 <!-- <i class="el-icon-close"></i> -->
                 <span class="el-upload-list__item-actions">
-                  <span class="el-upload-list__item-preview" @click="handlePictureCardPreviewImage(element)">
+                  <span
+                    class="el-upload-list__item-preview"
+                    @click="handlePictureCardPreviewImage(element)"
+                  >
                     <i class="el-icon el-icon--zoom-in">
-                      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024">
-                        <path fill="currentColor"
-                          d="m795.904 750.72 124.992 124.928a32 32 0 0 1-45.248 45.248L750.656 795.904a416 416 0 1 1 45.248-45.248zM480 832a352 352 0 1 0 0-704 352 352 0 0 0 0 704zm-32-384v-96a32 32 0 0 1 64 0v96h96a32 32 0 0 1 0 64h-96v96a32 32 0 0 1-64 0v-96h-96a32 32 0 0 1 0-64h96z">
-                        </path>
+                      <svg
+                        xmlns="http://www.w3.org/2000/svg"
+                        viewBox="0 0 1024 1024"
+                      >
+                        <path
+                          fill="currentColor"
+                          d="m795.904 750.72 124.992 124.928a32 32 0 0 1-45.248 45.248L750.656 795.904a416 416 0 1 1 45.248-45.248zM480 832a352 352 0 1 0 0-704 352 352 0 0 0 0 704zm-32-384v-96a32 32 0 0 1 64 0v96h96a32 32 0 0 1 0 64h-96v96a32 32 0 0 1-64 0v-96h-96a32 32 0 0 1 0-64h96z"
+                        ></path>
                       </svg>
                     </i>
                   </span>
                   <!-- remove -->
-                  <span class="el-upload-list__item-delete" @click="handleRemoveImage(element)">
+                  <span
+                    class="el-upload-list__item-delete"
+                    @click="handleRemoveImage(element)"
+                  >
                     <i class="el-icon el-icon--zoom-in">
-                      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024">
-                        <path fill="currentColor"
-                          d="M160 256H96a32 32 0 0 1 0-64h256V95.936a32 32 0 0 1 32-32h256a32 32 0 0 1 32 32V192h256a32 32 0 1 1 0 64h-64v672a32 32 0 0 1-32 32H192a32 32 0 0 1-32-32V256zm448-64v-64H416v64h192zM224 896h576V256H224v640zm192-128a32 32 0 0 1-32-32V416a32 32 0 0 1 64 0v320a32 32 0 0 1-32 32zm192 0a32 32 0 0 1-32-32V416a32 32 0 0 1 64 0v320a32 32 0 0 1-32 32z">
-                        </path>
+                      <svg
+                        xmlns="http://www.w3.org/2000/svg"
+                        viewBox="0 0 1024 1024"
+                      >
+                        <path
+                          fill="currentColor"
+                          d="M160 256H96a32 32 0 0 1 0-64h256V95.936a32 32 0 0 1 32-32h256a32 32 0 0 1 32 32V192h256a32 32 0 1 1 0 64h-64v672a32 32 0 0 1-32 32H192a32 32 0 0 1-32-32V256zm448-64v-64H416v64h192zM224 896h576V256H224v640zm192-128a32 32 0 0 1-32-32V416a32 32 0 0 1 64 0v320a32 32 0 0 1-32 32zm192 0a32 32 0 0 1-32-32V416a32 32 0 0 1 64 0v320a32 32 0 0 1-32 32z"
+                        ></path>
                       </svg>
                     </i>
                   </span>
@@ -214,9 +279,20 @@ const handleConfirmImagesShow = () => {
             </ul>
           </template>
           <template #footer>
-            <el-upload v-show="fileList.length < 9" class="unmove" :show-file-list="false" :accept="IMAGE_SUFFIX"
-              ref="uploadRef" v-model:file-list="fileList" action="#" :auto-upload="true" :limit="9"
-              list-type="picture-card" :http-request="handleUploadImage" :on-success="handleUploadImageSuccess">
+            <el-upload
+              v-show="fileList.length < 9"
+              class="unmove"
+              :show-file-list="false"
+              :accept="IMAGE_SUFFIX"
+              ref="uploadRef"
+              v-model:file-list="fileList"
+              action="#"
+              :auto-upload="true"
+              :limit="9"
+              list-type="picture-card"
+              :http-request="handleUploadImage"
+              :on-success="handleUploadImageSuccess"
+            >
               <el-icon>
                 <Plus />
               </el-icon>
@@ -229,7 +305,9 @@ const handleConfirmImagesShow = () => {
         <div class="dialog-footer flex-row flex-aic flex-jc-sb">
           <span class="dialog-footer__left">拖拽图片进行排序</span>
           <div class="dialog-footer__right">
-            <el-button type="primary" @click="handleConfirmImagesShow">确定</el-button>
+            <el-button type="primary" @click="handleConfirmImagesShow"
+              >确定</el-button
+            >
           </div>
         </div>
       </template>
@@ -237,7 +315,11 @@ const handleConfirmImagesShow = () => {
 
     <!-- Image Preview -->
     <el-dialog v-model="visibilityImagePreview" width="500">
-      <el-image style="width: 100%; max-width: 500px;" :src="imagePreviewUrl" fit="cover" />
+      <el-image
+        style="width: 100%; max-width: 500px"
+        :src="imagePreviewUrl"
+        fit="cover"
+      />
     </el-dialog>
   </div>
 </template>
@@ -250,7 +332,7 @@ const handleConfirmImagesShow = () => {
 
     .header {
       padding: 20px;
-      border-bottom: 1px solid #F6F6F6;
+      border-bottom: 1px solid #f6f6f6;
 
       .title {
         font-size: 16px;
@@ -280,7 +362,7 @@ const handleConfirmImagesShow = () => {
     }
 
     .footer {
-      border-top: 1px solid #F6F6F6;
+      border-top: 1px solid #f6f6f6;
       padding: 20px;
       padding-top: 30px;
     }

+ 283 - 4
src/views/forum/index.vue

@@ -1,5 +1,5 @@
 <script setup>
-import { computed, onMounted, ref } from "vue";
+import { computed, onMounted, ref, reactive } from "vue";
 import { ArrowRight } from "@element-plus/icons-vue";
 
 import Banner from "~/components/Banner/index.vue";
@@ -14,6 +14,114 @@ import { useForumIndex } from "~/useHook/useForum";
 import * as topic from "~/api/topic";
 import * as user from "~/api/user";
 import * as delApi from "~/api/forum";
+import * as topticApi from "~/api/topic";
+import { ElMessage } from "element-plus";
+import { CaretBottom, Search } from "@element-plus/icons-vue";
+//查看全部论坛
+const visibleDialog = ref(false);
+const isSearch = ref(false);
+const keyword = ref("");
+const leftShow = ref(true);
+const currentCategoryId = ref();
+const subjectList = ref([]);
+const childrenList = ref([]);
+
+const isFirst = ref(true); // 第一次会调用
+const __topic_category__ = async () => {
+  try {
+    const params = {};
+    const { data } = await topticApi.category(params);
+    if (data) {
+      if (data.length && isFirst.value) {
+        isFirst.value = false;
+        data[0].isSelected = true; // 默认第一项选中
+        currentCategoryId.value = data[0].id;
+        __topic_inlist__();
+      }
+      subjectList.value = data || [];
+    }
+  } catch (error) {}
+};
+const pagination = reactive({
+  page: 1,
+  limit: 10,
+});
+
+const __topic_inlist__ = async (type) => {
+  try {
+    const params = {
+      is_page: 1,
+      // category_id: currentCategoryId.value,
+      category_id: type == 1 ? " " : currentCategoryId.value,
+      title: keyword.value,
+      ...pagination,
+    };
+    const { data } = await topticApi.list(params);
+    if (data) {
+      Loading.value = false;
+      childrenList.value = data.list;
+      if (data.page === data.last_page) {
+        // 最后一页
+        isDisabledScroll.value = true;
+      }
+    }
+  } catch (error) {}
+};
+
+onMounted(__topic_category__);
+
+// 切换话题分类
+const handleChooseCategory = (category, idx) => {
+  if (currentCategoryId.value === category.id) return;
+
+  childrenList.value = [];
+  Loading.value = true;
+  currentCategoryId.value = category.id;
+
+  // reset pagination.
+  Object.assign(pagination, {
+    page: 1,
+    limit: 10,
+  });
+
+  __topic_inlist__();
+};
+
+// 加载列表数据
+const Loading = ref(false);
+const isDisabledScroll = ref(false);
+const handleLoadList = () => {
+  if (isDisabledScroll.value) return;
+  Loading.value = true;
+  // 加载下一页面
+  ++pagination.page;
+  __topic_inlist__();
+};
+
+// 搜索模块
+const handleSearchConfirm = () => {
+  if (!keyword.value.length) return ElMessage.error("关键词为空不允搜索");
+  __topic_inlist__(1);
+  leftShow.value = false;
+};
+
+// Clear keyword
+const handleClearEvent = () => {
+  Object.assign(pagination, {
+    page: 1,
+  });
+  __topic_inlist__();
+};
+
+// 确认点击模块
+const confirmTopic = ref(null);
+const handleClickTopic = (item) => {
+  confirmTopic.value = item;
+  handleLoadForumData({ topic_id: item.id });
+  visibleDialog.value = false;
+  leftShow.value = true;
+  keyword.value = "";
+};
 
 //删除
 const delect = async (id) => {
@@ -208,6 +316,7 @@ onMounted(() => {
       <div
         style="cursor: pointer"
         class="see-more flex-row flex-aic flex-jc-sb"
+        @click="visibleDialog = true"
       >
         <span>查看全部论坛</span>
         <el-icon :size="18">
@@ -243,24 +352,194 @@ onMounted(() => {
           </dd>
           <dd class="more" @click="tomore()">
             <span
-            
               style="cursor: pointer"
               v-if="totala.length > 5 && show == true"
               >查看更多话题</span
             >
           </dd>
         </div>
-        <div v-else style="display: flex;justify-content: center;align-items: center">
-          <div style="font-size: 15px;margin-top: 10px">暂无内容</div>
+        <div
+          v-else
+          style="display: flex; justify-content: center; align-items: center"
+        >
+          <div style="font-size: 15px; margin-top: 10px">暂无内容</div>
         </div>
       </dl>
     </div>
+    <el-dialog v-model="visibleDialog" title="选择话题" width="800px">
+      <div class="dialog__main">
+        <div class="search-wrapper flex-row">
+          <el-input v-model.trim="keyword" clearable @clear="handleClearEvent">
+            <template #prefix>
+              <el-icon :size="22">
+                <Search />
+              </el-icon>
+            </template>
+          </el-input>
+          <el-button type="primary" @click="handleSearchConfirm"
+            >搜索</el-button
+          >
+        </div>
+        <div class="choose-subject flex-row flex-jc-sb">
+          <!-- 搜索的话隐藏left块 -->
+          <div class="left" v-if="leftShow">
+            <ul>
+              <li
+                v-for="(item, idx) in subjectList"
+                :key="idx"
+                :class="[item.id === currentCategoryId ? 'active' : '']"
+                @click="handleChooseCategory(item, idx)"
+              >
+                <span>{{ item.name }}</span>
+              </li>
+            </ul>
+          </div>
+          <div class="right">
+            <ul
+              v-infinite-scroll="handleLoadList"
+              :infinite-scroll-distance="20"
+              :infinite-scroll-disabled="isDisabledScroll"
+              :infinite-scroll-immediate="false"
+              v-if="Loading || isSearch || childrenList.length"
+              class="scroll-optimize"
+            >
+              <li
+                v-for="(item, idx) in childrenList"
+                :key="idx"
+                @click="handleClickTopic(item)"
+              >
+                <span>{{ item.title }}</span>
+              </li>
+              <li v-if="Loading">加载中...</li>
+              <li v-if="isSearch" class="tips">已加载全部</li>
+            </ul>
+            <div class="empty" v-else>没有内容</div>
+          </div>
+        </div>
+      </div>
+      <!-- <template #footer>
+        <span class="dialog-footer">
+          <el-button @click="dialogVisible = false">Cancel</el-button>
+          <el-button type="primary" @click="dialogVisible = false">
+            Confirm
+          </el-button>
+        </span>
+      </template> -->
+    </el-dialog>
   </div>
 </template>
 
 <style lang="scss" scoped>
 @import "~/styles/variable.scss";
 
+.noline {
+  border: initial;
+}
+
+:deep(.el-input) {
+  --el-input-border-color: transparent;
+  --el-input-bg-color: transparent;
+  --el-input-focus-border-color: transparent;
+}
+
+.search-wrapper {
+  padding: 10px 6px;
+  background: #f5f5f5;
+  column-gap: 10px;
+  border-radius: 6px;
+
+  :deep(.el-input__wrapper:hover) {
+    box-shadow: initial;
+  }
+}
+
+.choose-subject {
+  padding-top: 20px;
+  column-gap: 30px;
+
+  ul {
+    list-style: none;
+    padding: 0;
+    margin: 0;
+  }
+
+  .left {
+    width: 130px;
+    // background-color: #fff;
+    background: #f5f5f5;
+    // max-height: 60px; /** 需要最大高度固定 */
+    overflow: auto;
+
+    &::-webkit-scrollbar {
+      width: 10px;
+      background-color: #fff;
+    }
+
+    &::-webkit-scrollbar-thumb {
+      background: #bdbdbd;
+      border-radius: 5px;
+    }
+
+    &::-webkit-scrollbar-thumb:hover {
+      background: #a0a0a0;
+    }
+
+    li {
+      text-align: center;
+      height: 52px;
+      line-height: 52px;
+      font-size: 16px;
+      font-weight: 500;
+      color: #999999;
+      cursor: pointer;
+
+      &.active {
+        background-color: #fff;
+        font-size: 16px;
+        font-weight: 500;
+        color: #333333;
+      }
+    }
+  }
+
+  .right {
+    width: 0;
+    flex: 1;
+
+    ul {
+      max-height: 500px;
+      overflow: auto;
+    }
+
+    li {
+      padding: 0 6px;
+      height: 52px;
+      line-height: 52px;
+      font-size: 16px;
+      font-weight: 500;
+      color: #333333;
+      border-bottom: 1px solid #f5f5f5;
+      cursor: pointer;
+
+      &:last-child {
+        border-bottom: initial;
+      }
+    }
+
+    .tips {
+      text-align: center;
+      font-size: 16px;
+      font-weight: 400;
+      color: rgba(51, 51, 51, 0.6);
+    }
+
+    .empty {
+      line-height: 10em;
+      text-align: center;
+    }
+  }
+}
+
 .forum {
   &-container {
     column-gap: 20px;

+ 8 - 6
src/views/forum/topic.vue

@@ -43,14 +43,16 @@ const __news__ = async () => {
 };
 
 onMounted(__news__);
-
+const topicid = ref();
+topicid.value = route.query.id
 //参加话题
 const jointopic = () => {
   router.push({
     path: "/forum/edit",
-    query:{
-      id:route.query.id
-    }
+    query: {
+      id: topicid.value,
+      title: toptitle.value,
+    },
   });
 };
 
@@ -63,7 +65,7 @@ const returnup = () => {
   router.go(-1);
 };
 </script>
-
+  
 <template>
   <div class="topic-container flex-row">
     <div class="topic__left-context">
@@ -74,7 +76,7 @@ const returnup = () => {
         </div>
         <div class="topic__header-main">
           <div class="topic-title">#{{ toptitle }}</div>
-          <p class="topic-descs">descssssss</p>
+          <p class="topic-descs">记录你生活的点点滴滴</p>
           <el-button type="primary" :icon="EditPen" @click="jointopic"
             >参与</el-button
           >

+ 523 - 7
src/views/index/components/SigninPrize.vue

@@ -1,10 +1,11 @@
 <script setup>
-import { ref, onMounted } from "vue";
+import { ref, onMounted, reactive } from "vue";
 import * as qianApi from "~/api/qiandao";
-
+import * as addApi from "~/api/address";
 const prize = ref([]);
 const total = ref(0);
 const show = ref(false);
+//商品列表
 const __prizeList__ = async () => {
   try {
     const { data } = await qianApi.prize({
@@ -19,18 +20,223 @@ const __prizeList__ = async () => {
 };
 
 onMounted(__prizeList__);
+//打开模态框
+//地址更换
+const ind = ref(0);
+const change = (idx, id) => {
+  ind.value = idx;
+  defaultid.value = id;
+};
+//地址详情
+const info = () => {
+  if (defaultid.value) {
+    infoa();
+  } else {
+    ElMessage.warning({
+      message: "请选择地址",
+      type: "warning",
+    });
+  }
+};
+const infoa = async () => {
+  try {
+    const { data } = await addApi.info({
+      id: defaultid.value,
+    });
+    defaultadd.value[0] = data;
+    dialogVisible.value = false;
+  } catch (error) {}
+  receive();
+};
+//获取地址列表
+const imageshow = ref(false);
+const arrlist = ref([]);
+//默认地址
+const defaultid = ref();
+const defaultadd = ref([]);
+const list = async () => {
+  try {
+    const { data } = await addApi.list({
+      is_page: 0,
+    });
+    arrlist.value = data;
+    var defaultAddress = [];
+    data.forEach((item) => {
+      if (item.is_default == 1) {
+        defaultAddress.push(item);
+      }
+    });
+    defaultadd.value = defaultAddress;
+    defaultid.value = defaultAddress[0].id;
+  } catch (error) {}
+};
+onMounted(list);
 const address_id = ref(0);
-
 //领取
-const get = async (id) => {
+const dialogVisible = ref(false);
+const goodsid = ref(0);
+const get = (id, type) => {
+  goodsid.value = id;
+  if (type != "integral") {
+    dialogVisible.value = true;
+  } else {
+    receive();
+  }
+};
+//领取商品
+const receive = async () => {
   try {
     const { data } = await qianApi.receive({
+      address_id: defaultid.value,
+      id: goodsid.value,
+    });
+    ElMessage.success({
+      message: "领取成功",
+      type: "success",
+    });
+    __prizeList__();
+  } catch (error) {}
+};
+//弹出框
+const dialogFormVisible = ref(false);
+const form = reactive({
+  name: "",
+  mobile: "",
+  province_id: "",
+  city_id: "",
+  district_id: "",
+  address: "",
+  is_default: 0,
+});
+
+//编辑
+const compilevalue = ref(0);
+const compileid = ref();
+const compile = (id) => {
+  compilevalue.value = 1;
+  compileid.value = id;
+  dialogFormVisible.value = true;
+  __addinfo__(id);
+};
+//详情
+const __addinfo__ = async (id) => {
+  try {
+    const { data } = await addApi.info({
       id: id,
-      address_id: address_id.value,
     });
-    // __prizeList__()
+    form.name = data.name;
+    form.mobile = data.mobile;
+    form.province_id = data.province_id;
+    form.city_id = data.city_id;
+    form.district_id = data.district_id;
+    form.address = data.address;
+    form.is_default = data.is_default;
+    provincename.value = data.province_name;
+    cityname.value = data.city_name;
+    districtname.value = data.district_name;
   } catch (error) {}
 };
+//省级切换
+const province = (value) => {
+  __errlist__(value.id);
+  provincename.value = value.name;
+  form.province_id = value.id;
+};
+const city = (value) => {
+  console.log(value);
+  __citylist__(value.id);
+  cityname.value = value.name;
+  form.city_id = value.id;
+};
+const districtname = ref();
+const district = (value) => {
+  districtname.value = value.name;
+  form.district_id = value.id;
+};
+//保存地址
+const saveadd = () => {
+  if (compilevalue.value == 1) {
+    __put__();
+  } else {
+    __multipart__();
+  }
+};
+//添加
+const __multipart__ = async () => {
+  try {
+    const { data } = await addApi.multipart({
+      ...form,
+      is_default: 0,
+    });
+    dialogFormVisible.value = false;
+    ElMessage.success({
+      message: "添加成功",
+      type: "success",
+    });
+    list();
+  } catch (error) {}
+};
+//更新
+const __put__ = async () => {
+  try {
+    const { data } = await addApi.put({
+      id: compileid.value,
+      ...form,
+    });
+    dialogFormVisible.value = false;
+    compilevalue.value = 0;
+    form.name = "";
+    form.mobile = "";
+    form.province_id = "";
+    form.city_id = "";
+    form.district_id = "";
+    form.address = "";
+    form.is_default = "";
+    provincename.value = "";
+    cityname.value = "";
+    districtname.value = "";
+    ElMessage.success({
+      message: "编辑成功",
+      type: "success",
+    });
+    list();
+  } catch (error) {}
+};
+//地区列表
+const provincename = ref();
+const cityname = ref();
+const addlista = ref(0);
+const arealistb = ref([]);
+const __addlist__ = async () => {
+  try {
+    const { data } = await addApi.arealist({
+      parent_id: addlista.value,
+    });
+    arealistb.value = data;
+  } catch (error) {}
+};
+onMounted(__addlist__);
+// 地区
+const arealistc = ref([]);
+const __errlist__ = async (id) => {
+  try {
+    const { data } = await addApi.arealist({
+      parent_id: id,
+    });
+    arealistc.value = data;
+  } catch (error) {}
+};
+//区
+const citylist = ref([]);
+const __citylist__ = async (id) => {
+  try {
+    const { data } = await addApi.arealist({
+      parent_id: id,
+    });
+    citylist.value = data;
+  } catch (error) {}
+};
+
 const more = async () => {
   try {
     const { data } = await qianApi.prize({
@@ -59,6 +265,14 @@ const more = async () => {
       >
         <div class="info flex-row">
           <img
+            v-if="item.prize_type == 'integral'"
+            src="../../../assets/jifen.png"
+            style="width: 40px; height: 40px; border-radius: 4px"
+            alt=""
+            class="pic"
+          />
+          <img
+            v-else
             :src="item.prize_image"
             style="width: 40px; height: 40px; border-radius: 4px"
             alt=""
@@ -78,7 +292,7 @@ const more = async () => {
           已领取
         </el-button>
         <el-button
-          @click="get(item.id)"
+          @click="get(item.id, item.prize_type)"
           v-else-if="item.can_receive === 1 && item.is_receive == 0"
           type="primary"
         >
@@ -88,10 +302,312 @@ const more = async () => {
       </div>
     </div>
   </div>
+  <!-- 地址选择 -->
+  <el-dialog title="地址选择" v-model="dialogVisible" width="652px">
+    <div style="" v-if="arrlist.length > 0">
+      <div
+        :class="ind == idx ? 'activeb' : 'active1'"
+        style="
+          display: flex;
+          justify-content: space-between;
+          margin-top: 16px;
+          align-items: center;
+        "
+        v-for="(item, idx) in arrlist"
+        :key="idx"
+        @click="change(idx, item.id)"
+      >
+        <div>
+          <div>
+            <span class="namea">{{ item.name }}</span>
+            <span class="namea" style="margin-left: 5px">{{
+              item.mobile
+            }}</span>
+          </div>
+          <div class="address">{{ item.full_address }}</div>
+        </div>
+        <div class="compile" style="cursor: pointer" @click="compile(item.id)">
+          编辑
+        </div>
+      </div>
+    </div>
+    <div style="text-align: center; margin: 10px 0" v-else>暂无数据</div>
+    <div class="btn">
+      <span style="color: rgba(0, 176, 176, 1); font-size: 20px">+</span>
+      <span
+        style="margin-left: 3px; color: rgba(0, 176, 176, 1); cursor: pointer"
+        @click="dialogFormVisible = true"
+        >新增</span
+      >
+    </div>
+    <template #footer>
+      <span class="dialog-footer">
+        <el-button @click="dialogVisible = false">取 消</el-button>
+        <el-button type="primary" @click="info">确 定</el-button>
+      </span>
+    </template>
+  </el-dialog>
+  <!-- 弹出框 -->
+  <el-dialog
+    style="width: 540px"
+    title="添加收货地址"
+    v-model="dialogFormVisible"
+  >
+    <el-form
+      :model="form"
+      :rules="rules"
+      label-position="right"
+      label-width="100px"
+    >
+      <el-form-item prop="name" label="收货人" :label-width="formLabelWidth">
+        <el-input
+          style="width: 378px"
+          v-model="form.name"
+          placeholder="请输入"
+        ></el-input>
+      </el-form-item>
+      <el-form-item label="所在地区" :label-width="formLabelWidth">
+        <el-select
+          style="width: 118px"
+          v-model="provincename"
+          prop="region"
+          placeholder="请选择"
+          @change="province"
+        >
+          <el-option
+            v-for="(item, idx) in arealistb"
+            :key="idx"
+            :label="item.name"
+            :value="item"
+          ></el-option>
+        </el-select>
+        <el-select
+          style="width: 118px; margin-left: 12px"
+          v-model="cityname"
+          placeholder="请选择"
+          @change="city"
+        >
+          <el-option
+            v-for="(item, idx) in arealistc"
+            :key="idx"
+            :label="item.name"
+            :value="item"
+          ></el-option>
+        </el-select>
+        <el-select
+          style="width: 118px; margin-left: 12px"
+          v-model="districtname"
+          placeholder="请选择"
+          @change="district"
+        >
+          <el-option
+            v-for="(item, idx) in citylist"
+            :key="idx"
+            :label="item.name"
+            :value="item"
+          ></el-option>
+        </el-select>
+      </el-form-item>
+      <el-form-item prop="name" label="详细地址" :label-width="formLabelWidth">
+        <el-input
+          style="width: 378px"
+          v-model="form.address"
+          placeholder="请输入"
+        ></el-input>
+      </el-form-item>
+      <el-form-item prop="name" label="手机号码" :label-width="formLabelWidth">
+        <el-input
+          style="width: 378px"
+          v-model="form.mobile"
+          placeholder="请输入"
+        ></el-input>
+      </el-form-item>
+      <el-form-item label="设为默认地址" :label-width="formLabelWidth">
+        <!-- <el-radio-group > -->
+        <el-radio v-model="form.is_default" :label="1">是</el-radio>
+        <el-radio v-model="form.is_default" :label="0">否</el-radio>
+        <!-- </el-radio-group> -->
+      </el-form-item>
+    </el-form>
+    <div style="" class="saveadd" @click="saveadd">保存收货地址</div>
+  </el-dialog>
 </template>
 
 <style lang="scss" scoped>
 @import "~/styles/variable.scss";
+.saveadd {
+  width: 122px;
+  height: 40px;
+  background: #00b0b0;
+  border-radius: 4px;
+  font-family: PingFangSC, PingFang SC;
+  font-weight: 400;
+  font-size: 15px;
+  color: #ffffff;
+  line-height: 40px;
+  text-align: center;
+  font-style: normal;
+  cursor: pointer;
+}
+.btn {
+  width: 84px;
+  height: 38px;
+  border-radius: 4px;
+  border: 1px solid #57c3c2;
+  text-align: center;
+  line-height: 38px;
+  margin-top: 16px;
+}
+.address {
+  font-family: PingFangSC, PingFang SC;
+  font-weight: 400;
+  font-size: 12px;
+  color: #999999;
+  line-height: 17px;
+  text-align: right;
+  font-style: normal;
+  margin-top: 6px;
+}
+.name {
+  font-family: PingFangSC, PingFang SC;
+  font-weight: 500;
+  font-size: 17px;
+  color: #000000;
+  line-height: 24px;
+  text-align: right;
+  font-style: normal;
+}
+.compile {
+  width: 80px;
+  height: 35px;
+  background: #00b0b0;
+  border-radius: 4px;
+  font-family: PingFangSC, PingFang SC;
+  font-weight: 400;
+  font-size: 14px;
+  color: #ffffff;
+  line-height: 35px;
+  text-align: center;
+  font-style: normal;
+}
+.active1 {
+  background: #ffffff;
+  border-radius: 4px;
+  border: 1px solid #d1d1d1;
+  padding: 16px 24px 16px;
+}
+.activeb {
+  background: #ffffff;
+  border-radius: 4px;
+  border: 1px solid #00b0b0;
+  padding: 16px 24px 16px;
+}
+
+.usea {
+  width: 94px;
+  height: 42px;
+  background: #cecece;
+  border-radius: 4px;
+  font-weight: 400;
+  font-size: 16px;
+  color: #ffffff;
+  line-height: 42px;
+  text-align: center;
+  font-style: normal;
+  cursor: pointer;
+}
+.info {
+  font-family: PingFangSC, PingFang SC;
+  font-weight: 400;
+  font-size: 14px;
+  color: #666666;
+  line-height: 20px;
+  text-align: left;
+  font-style: normal;
+  margin-top: 10px;
+}
+.title {
+  font-family: PingFangSC, PingFang SC;
+  font-weight: 500;
+  font-size: 16px;
+  color: #333333;
+  line-height: 22px;
+  text-align: left;
+  font-style: normal;
+}
+.use {
+  font-family: PingFangSC, PingFang SC;
+  font-weight: 400;
+  font-size: 13px;
+  color: #333333;
+  line-height: 18px;
+  text-align: left;
+  font-style: normal;
+  margin-top: 10px;
+}
+.date {
+  font-family: SFPro, SFPro;
+  font-weight: 400;
+  font-size: 14px;
+  color: #777777;
+  line-height: 16px;
+  text-align: left;
+  font-style: normal;
+  margin-top: 27px;
+}
+.button {
+  width: 108px;
+  height: 44px;
+  background: #00b0b0;
+  border-radius: 4px;
+  font-family: PingFangSC, PingFang SC;
+  font-weight: 400;
+  font-size: 16px;
+  color: #ffffff;
+  line-height: 44px;
+  text-align: center;
+  font-style: normal;
+}
+.font {
+  padding-top: 38px;
+  box-sizing: border-box;
+  text-align: center;
+  background: url(../../../assets/count/discounts.png) no-repeat;
+  width: 180px;
+  height: 140px;
+  background-size: 100%;
+  font-family: JDZhengHT, JDZhengHT;
+  font-weight: 400;
+  font-size: 22px;
+  color: #ffffff;
+  line-height: 27px;
+}
+.font1 {
+  padding-top: 38px;
+  box-sizing: border-box;
+  text-align: center;
+  background: url(../../../assets/count/lostBack.png) no-repeat;
+  width: 180px;
+  height: 140px;
+  background-size: 100%;
+  font-family: JDZhengHT, JDZhengHT;
+  font-weight: 400;
+  font-size: 22px;
+  color: #ffffff;
+  line-height: 27px;
+}
+.box {
+  // width: 714px;
+  height: 100px;
+  background: #f7f7f7;
+  border-radius: 6px;
+  padding: 20px;
+  box-sizing: border-box;
+  margin-top: 20px;
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+}
 
 .signin-prize-container {
   padding: 16px;

+ 295 - 1
src/views/index/content.vue

@@ -11,6 +11,9 @@ import TheCharts from "~/components/TheCharts/index.vue";
 import Banner from "~/components/Banner/index.vue";
 import ErrorReport from "~/components/ErrorReport/index.vue";
 import { useRouter } from "vue-router";
+import * as topticApi from "~/api/topic";
+import { ElMessage } from "element-plus";
+import { CaretBottom, Search } from "@element-plus/icons-vue";
 const router = useRouter();
 
 import * as newsApi from "~/api/news";
@@ -196,9 +199,193 @@ const topicinfo = (id) => {
     },
   });
 };
+//大家在聊
+const visibleDialog = ref(false);
+const isSearch = ref(false);
+const keyword = ref("");
+const leftShow = ref(true);
+const currentCategoryId = ref();
+const subjectList = ref([]);
+const childrenList = ref([]);
+
+const topicMore = () => {
+  visibleDialog.value = true;
+};
+const isFirst = ref(true); // 第一次会调用
+const __topic_category__ = async () => {
+  try {
+    const params = {};
+    const { data } = await topticApi.category(params);
+    if (data) {
+      if (data.length && isFirst.value) {
+        isFirst.value = false;
+        data[0].isSelected = true; // 默认第一项选中
+        currentCategoryId.value = data[0].id;
+        __topic_inlist__();
+      }
+      subjectList.value = data || [];
+    }
+  } catch (error) {}
+};
+const pagination = reactive({
+  page: 1,
+  limit: 10,
+});
+
+const __topic_inlist__ = async (type) => {
+  try {
+    const params = {
+      is_page: 1,
+      category_id: type == 1 ? " " : currentCategoryId.value,
+      title: keyword.value,
+      ...pagination,
+    };
+    const { data } = await topticApi.list(params);
+    if (data) {
+      Loading.value = false;
+      childrenList.value = data.list;
+      if (data.page === data.last_page) {
+        // 最后一页
+        isDisabledScroll.value = true;
+      }
+    }
+  } catch (error) {}
+};
+
+onMounted(__topic_category__);
+
+// 切换话题分类
+const handleChooseCategory = (category, idx) => {
+  if (currentCategoryId.value === category.id) return;
+
+  childrenList.value = [];
+  Loading.value = true;
+  currentCategoryId.value = category.id;
+
+  // reset pagination.
+  Object.assign(pagination, {
+    page: 1,
+    limit: 10,
+  });
+
+  __topic_inlist__();
+};
+
+// 加载列表数据
+const Loading = ref(false);
+const isDisabledScroll = ref(false);
+const handleLoadList = () => {
+  if (isDisabledScroll.value) return;
+  Loading.value = true;
+  // 加载下一页面
+  ++pagination.page;
+  __topic_inlist__();
+};
+
+// 搜索模块
+const handleSearchConfirm = () => {
+  if (!keyword.value.length) return ElMessage.error("关键词为空不允搜索");
+  __topic_inlist__();
+  leftShow.value = false;
+};
+
+// Clear keyword
+const handleClearEvent = () => {
+  Object.assign(pagination, {
+    page: 1,
+  });
+  __topic_inlist__();
+};
+
+// 确认点击模块
+const confirmTopic = ref(null);
+const handleClickTopic = (item) => {
+  confirmTopic.value = item;
+  router.push({
+    path: "/forum/topic/:id",
+    query: {
+      id: item.id,
+    },
+  });
+  visibleDialog.value = false;
+  leftShow.value = true;
+  keyword.value = "";
+};
+// useScrollEvent({
+//   callback: handleGetScrollEnd,
+// });
+
+// const isCType = computed(
+//   () => (type) => type === forumType.value ? "active" : ""
+// );
+
+// const {
+//   forumType,
+//   forumTableData,
+//   handleLoadForumData,
+//   handleSwitchForumType,
+// } = useForumIndex();
+
+// console.log("%c forumty >>>", "background: blue; color: #fff", forumType.value);
+
+// const handleRefreshListData = () => {
+//   handleLoadForumData();
+//   handleSwitchForumType();
+//   useForumIndex();
+// };
 </script>
 
 <template>
+  <el-dialog v-model="visibleDialog" title="选择话题" width="800px">
+    <div class="dialog__main">
+      <div class="search-wrapper flex-row">
+        <el-input v-model.trim="keyword" clearable @clear="handleClearEvent">
+          <template #prefix>
+            <el-icon :size="22">
+              <Search />
+            </el-icon>
+          </template>
+        </el-input>
+        <el-button type="primary" @click="handleSearchConfirm">搜索</el-button>
+      </div>
+      <div class="choose-subject flex-row flex-jc-sb">
+        <!-- 搜索的话隐藏left块 -->
+        <div class="left" v-if="leftShow">
+          <ul>
+            <li
+              v-for="(item, idx) in subjectList"
+              :key="idx"
+              :class="[item.id === currentCategoryId ? 'active' : '']"
+              @click="handleChooseCategory(item, idx)"
+            >
+              <span>{{ item.name }}</span>
+            </li>
+          </ul>
+        </div>
+        <div class="right">
+          <ul
+            v-infinite-scroll="handleLoadList"
+            :infinite-scroll-distance="20"
+            :infinite-scroll-disabled="isDisabledScroll"
+            :infinite-scroll-immediate="false"
+            v-if="Loading || isSearch || childrenList.length"
+            class="scroll-optimize"
+          >
+            <li
+              v-for="(item, idx) in childrenList"
+              :key="idx"
+              @click="handleClickTopic(item)"
+            >
+              <span>{{ item.title }}</span>
+            </li>
+            <li v-if="Loading">加载中...</li>
+            <li v-if="isSearch" class="tips">已加载全部</li>
+          </ul>
+          <div class="empty" v-else>没有内容</div>
+        </div>
+      </div>
+    </div>
+  </el-dialog>
   <div class="index-container">
     <div class="banner">
       <Banner type="index" />
@@ -270,7 +457,7 @@ const topicinfo = (id) => {
         />
       </template>
     </div>
-    <IndexTitle title="大家在聊" />
+    <IndexTitle @seeMore="topicMore" title="大家在聊" />
     <div class="tags-container flex-row">
       <template v-for="(item, idx) in topicList" :key="idx">
         <div @click="topicinfo(item.id)" class="tagbox">
@@ -328,6 +515,113 @@ const topicinfo = (id) => {
 </template>
 
 <style lang="scss" scoped>
+.noline {
+  border: initial;
+}
+
+:deep(.el-input) {
+  --el-input-border-color: transparent;
+  --el-input-bg-color: transparent;
+  --el-input-focus-border-color: transparent;
+}
+
+.search-wrapper {
+  padding: 10px 6px;
+  background: #f5f5f5;
+  column-gap: 10px;
+  border-radius: 6px;
+
+  :deep(.el-input__wrapper:hover) {
+    box-shadow: initial;
+  }
+}
+
+.choose-subject {
+  padding-top: 20px;
+  column-gap: 30px;
+
+  ul {
+    list-style: none;
+    padding: 0;
+    margin: 0;
+  }
+
+  .left {
+    width: 130px;
+    // background-color: #fff;
+    background: #f5f5f5;
+    // max-height: 60px; /** 需要最大高度固定 */
+    overflow: auto;
+
+    &::-webkit-scrollbar {
+      width: 10px;
+      background-color: #fff;
+    }
+
+    &::-webkit-scrollbar-thumb {
+      background: #bdbdbd;
+      border-radius: 5px;
+    }
+
+    &::-webkit-scrollbar-thumb:hover {
+      background: #a0a0a0;
+    }
+
+    li {
+      text-align: center;
+      height: 52px;
+      line-height: 52px;
+      font-size: 16px;
+      font-weight: 500;
+      color: #999999;
+      cursor: pointer;
+
+      &.active {
+        background-color: #fff;
+        font-size: 16px;
+        font-weight: 500;
+        color: #333333;
+      }
+    }
+  }
+
+  .right {
+    width: 0;
+    flex: 1;
+
+    ul {
+      max-height: 500px;
+      overflow: auto;
+    }
+
+    li {
+      padding: 0 6px;
+      height: 52px;
+      line-height: 52px;
+      font-size: 16px;
+      font-weight: 500;
+      color: #333333;
+      border-bottom: 1px solid #f5f5f5;
+      cursor: pointer;
+
+      &:last-child {
+        border-bottom: initial;
+      }
+    }
+
+    .tips {
+      text-align: center;
+      font-size: 16px;
+      font-weight: 400;
+      color: rgba(51, 51, 51, 0.6);
+    }
+
+    .empty {
+      line-height: 10em;
+      text-align: center;
+    }
+  }
+}
 .index {
   &-container {
     .banner {

+ 17 - 33
src/views/index/follow.vue

@@ -16,28 +16,10 @@ import { ref, onMounted, reactive, onActivated } from "vue";
 import * as userApi from "~/api/user";
 import * as summary from "~/api/gather";
 import { useRouter } from "vue-router";
+import { useUser } from "~/store/user";
 const router = useRouter();
+const user = useUser();
 //用户信息
-// let userInfo = ref([{}]);
-// const __news__ = async () => {
-//   try {
-//     const { data } = await userApi.list({});
-//     userInfo.value = data;
-//     __follow__(data.id);
-//   } catch (error) {}
-// };
-// __news__();
-
-// //关注
-// const folow = ref("");
-// const __follow__ = async (id) => {
-//   try {
-//     const { data } = await userApi.follow({
-//       id: id,
-//     });
-//     folow.value = data;
-//   } catch (error) {}
-// };
 //关注的内容
 const tableData = ref([]);
 const summarya = async () => {
@@ -99,26 +81,28 @@ const todetail = (type, id) => {
     });
   }
 };
+const User = localStorage.getItem("USER_STORE");
+console.log("token", User);
 </script>
 
 <template>
   <div class="index-follow-container flex-row flex-jc-sb">
     <div class="context">
       <!-- 尚未登录组件 -->
-      <UnloginContent />
+      <UnloginContent v-if="token == ''" />
 
       <!-- 登录但是无关注用户发动态 -->
-      <div v-if="tableData.length>0">
-        <template  v-for="(item, idx) in tableData" :key="idx">
-        <MomentLayout
-          @other="other(item.user_id)"
-          :type="item.source_type"
-          :detail="item"
-          @refresh="handleRefreshListData"
-          @detail="todetail(item.source_type, item.source_id)"
-          add='fllow'
-        />
-      </template>
+      <div v-if="tableData.length > 0">
+        <template v-for="(item, idx) in tableData" :key="idx">
+          <MomentLayout
+            @other="other(item.user_id)"
+            :type="item.source_type"
+            :detail="item"
+            @refresh="handleRefreshListData"
+            @detail="todetail(item.source_type, item.source_id)"
+            add="fllow"
+          />
+        </template>
       </div>
       <!-- <MomentLayout /> -->
       <FloowEmpty v-else />
@@ -150,7 +134,7 @@ const todetail = (type, id) => {
 
 .index-follow-container {
   max-width: 1440px;
-  padding: 0 76px;
+  // padding: 0 76px;
   column-gap: 24px;
   margin: 0 auto;
 

+ 81 - 28
src/views/market/placeOrder.vue

@@ -12,8 +12,21 @@ import Servicer from "~/components/Servicer/index.vue";
 import * as addApi from "~/api/address";
 import * as jifenApi from "~/api/jifen";
 import * as userApi from "~/api/user";
-
+import { useUser } from "~/store/user";
 import * as commonApi from "~/api/common";
+const User = useUser();
+//等级优惠列表
+const level_discount = ref([
+  {
+    value: 0,
+    label: "不使用",
+  },
+  {
+    value: 1,
+    label: "使用",
+  },
+]);
+
 //添加客服接口
 const imageshow = ref(false);
 const customer_service_qrcode = ref();
@@ -23,6 +36,7 @@ const getConfiguser = async () => {
       module: "basic",
     });
     customer_service_qrcode.value = data.customer_service_qrcode;
+    visibilityDialog2.value = false;
   } catch (error) {}
   imageshow.value = true;
 };
@@ -106,7 +120,7 @@ const __multipart__ = async () => {
       message: "添加成功",
       type: "success",
     });
-    list()
+    list();
   } catch (error) {}
 };
 //更新
@@ -132,7 +146,7 @@ const __put__ = async () => {
       message: "编辑成功",
       type: "success",
     });
-    list()
+    list();
   } catch (error) {}
 };
 //地区列表
@@ -184,6 +198,16 @@ const couponid = ref();
 const changeyou = (idx) => {
   couponid.value = coupon.value[idx].id;
   you.value = coupon.value[idx].coupon.amount;
+  console.log("couponid", couponid);
+  __calculate__();
+};
+
+const changeis_level_discount = (index) => {
+  console.log(index);
+  is_level_discount.value = level_discount.value[index].value;
+  console.log("is_level_discount", is_level_discount);
+  __calculate__();
+  // you.value = coupon.value[idx].coupon.amount;
 };
 
 //获取商品详情
@@ -261,7 +285,18 @@ const __coupon__ = async () => {
       is_use: 0,
       type: "integral",
     });
-    coupon.value = data;
+    var arr = [];
+    data.forEach((item) => {
+      // console.log(goodsInfo.price * count);
+      // console.log((item.coupon.type == "integral_threshold" && goodsInfo.value.price * count.value >= item.coupon.threshold ));
+      if (
+        (item.coupon.type == "integral_threshold" && goodsInfo.value.price * count.value >= item.coupon.threshold ) || item.coupon.type != "integral_threshold"
+      ) {
+        console.log(item);
+        arr.push(item);
+      }
+      coupon.value = arr;
+    });
   } catch (error) {}
 };
 onMounted(__coupon__);
@@ -269,6 +304,13 @@ onMounted(__coupon__);
 const value = ref("");
 
 const visibilityDialog = ref(false);
+const is_level_discount = ref(0);
+const coupon_discount = ref(0);
+const leveldiscount = ref(0);
+const total_discount = ref(0);
+const delivery_fee = ref(0);
+const pay_price = ref(0);
+const total_price = ref(0);
 //下单前计算
 const __calculate__ = async () => {
   try {
@@ -276,15 +318,20 @@ const __calculate__ = async () => {
       goods_id: route.query.id,
       goods_count: route.query.count,
       coupon_id: couponid.value,
-      is_level_discount: "1",
+      is_level_discount: is_level_discount.value,
       address_id: defaultid.value,
     });
+    coupon_discount.value = data.price_data.coupon_discount;
+    leveldiscount.value = data.price_data.level_discount;
+    total_discount.value = data.price_data.total_discount;
+    delivery_fee.value = data.price_data.delivery_fee;
+    pay_price.value = data.price_data.pay_price;
+    total_price.value = data.price_data.total_price;
   } catch (error) {}
 };
 //立即兑换
 const handleConfirmChange = () => {
   visibilityDialog.value = true;
-  __calculate__();
 };
 const handleConfirmBtn = () => {
   visibilityDialog.value = false;
@@ -298,7 +345,7 @@ const __place__ = async () => {
       goods_id: route.query.id,
       goods_count: route.query.count,
       coupon_id: couponid.value,
-      is_level_discount: "1",
+      is_level_discount: is_level_discount.value,
       address_id: defaultid.value,
     });
     visibilityDialog2.value = true;
@@ -401,28 +448,34 @@ const dialogVisible = ref(false);
             />
           </el-select>
           <div class="integralbox">
-            优惠<span>{{ you }}</span
+            优惠<span>{{ coupon_discount }}</span
             >积分
           </div>
         </li>
         <!-- 会员等级优惠 -->
-        <li>
-          <span class="label">会员等级优惠</span>
-          <el-select
-            v-model="value"
-            class="m-2"
-            placeholder="请选择"
-            size="large"
-          >
-            <el-option
-              v-for="item in coupon"
-              :key="item.value"
-              :label="item.label"
-              :value="item.value"
-            />
-          </el-select>
-          <div class="integralbox"><span>-0</span>积分</div>
-        </li>
+        <div v-if="User.is_vip">
+          <li>
+            <span class="label">会员等级优惠</span>
+            <el-select
+              v-model="is_level_discount"
+              class="m-2"
+              placeholder="请选择"
+              size="large"
+              @change="changeis_level_discount"
+            >
+              <el-option
+                v-for="(item, index) in level_discount"
+                :key="index"
+                :label="item.label"
+                :value="index"
+              />
+            </el-select>
+            <div class="integralbox">
+              <span>{{ leveldiscount }}</span
+              >积分
+            </div>
+          </li>
+        </div>
       </ul>
     </div>
 
@@ -435,16 +488,16 @@ const dialogVisible = ref(false);
       </li>
       <li>
         <span class="label">优惠积分:</span>
-        <span class="value">{{ you }}</span>
+        <span class="value">{{ total_discount }}</span>
       </li>
       <li>
         <span class="label">运费:</span>
-        <span class="value">包邮</span>
+        <span class="value">{{ delivery_fee || "包邮" }}</span>
       </li>
     </ul>
 
     <div class="place-order-sumtxt">
-      应付积分<span>{{ result() }}</span>
+      应付积分<span>{{ goodsInfo.price * count - total_discount }}</span>
     </div>
 
     <div class="place-order-footer">

+ 60 - 5
src/views/personal/components/ExperienceCard.vue

@@ -32,19 +32,65 @@ const __task__ = async () => {
 onMounted(__task__);
 
 //跳转
+//任务跳转
 const tosuccess = (type) => {
+  if (type == "like") {
+    router.push({
+      path: "/articles",
+    });
+  }
   if (type == "browse") {
-    router.replace({
-      name: "Forum",
+    router.push({
+      path: "/forum",
+    });
+  }
+  if (type == "create_post") {
+    router.push({
+      path: "/forum",
     });
   }
+  if (type == "invite") {
+    router.push({
+      path: "/setting",
+      query: {
+        subNavCurrent: "invite",
+      },
+    });
+  }
+  if (type == "share_post") {
+    router.push({
+      path: "/articles",
+    });
+  }
+  if (type == "finish_info") {
+    router.push({
+      path: "/setting",
+    });
+  }
+  if (type == "vip") {
+    pan.value = true;
+  }
 };
+
 //编辑信息
 const toinfo = () => {
   router.push({
     path: "/setting",
   });
 };
+//任务列表领取奖励
+const togetb = async (id) => {
+  try {
+    const { data } = await taskApi.task({
+      id: id,
+    });
+    ElMessage({
+      message: "领取成功",
+      type: "success",
+    });
+    __task__();
+  } catch (error) {}
+};
 </script>
 
 <template>
@@ -97,14 +143,23 @@ const toinfo = () => {
                     </div>
                   </div>
                   <div
-                    @click="tosuccess(item.source_type)"
                     class="success"
-                    v-if="item.status == 'finished'"
+                    v-if="item.status == 'received'"
+                    style="background: #d7d7d7"
                   >
                     已完成
                   </div>
                   <div
                     class="success"
+                    v-if="item.status == 'finished'"
+                    @click="togetb(item.id)"
+                    style="background: #00b0b0"
+                  >
+                    领取奖励
+                  </div>
+                  <div
+                    @click="tosuccess(item.source_type)"
+                    class="success"
                     v-if="item.status == 'pending'"
                     style="background: #00b0b0"
                   >
@@ -172,7 +227,7 @@ const toinfo = () => {
 .success {
   width: 56px;
   height: 24px;
-  background: #d7d7d7;
+  background: #acacac;
   border-radius: 14px;
   line-height: 24px;
   font-family: PingFangSC, PingFang SC;

+ 22 - 2
src/views/personal/components/qiandao.vue

@@ -23,6 +23,13 @@
       <div style="display: flex">
         <div>
           <img
+            v-if="item.prize_type == 'integral'"
+            src="../../../assets/jifen.png"
+            alt=""
+            style="width: 60px; height: 60px"
+          />
+          <img
+            v-else
             :src="item.prize_image"
             alt=""
             style="width: 60px; height: 60px"
@@ -34,7 +41,12 @@
         </div>
       </div>
       <div>
-        <div class="usea" v-if="item.is_receive == 1">已领取</div>
+        <div
+          class="usea"
+          v-if="item.is_receive == 1 && item.prize_type == 'integral'"
+        >
+          已领取
+        </div>
         <div
           class="usea"
           style="background: #ff6700"
@@ -66,6 +78,13 @@
       <div style="display: flex">
         <div>
           <img
+            v-if="item.prize_type == 'integral'"
+            src="../../../assets/jifen.png"
+            alt=""
+            style="width: 60px; height: 60px"
+          />
+          <img
+            v-else
             :src="item.prize_image"
             alt=""
             style="width: 60px; height: 60px"
@@ -491,8 +510,9 @@ const getConfiguser = async () => {
       module: "basic",
     });
     customer_service_qrcode.value = data.customer_service_qrcode;
+    visibilityDialog2.value = false;
+    imageshow.value = true;
   } catch (error) {}
-  imageshow.value = true;
 };
 //更新
 const __put__ = async () => {

+ 14 - 5
src/views/personal/components/sett.vue

@@ -198,7 +198,9 @@
       </div>
       <div style="margin-top: 33px; display: flex; align-items: center">
         <div class="phone">微信</div>
-        <div style="margin-left: 22px; min-width: 95px" class="phone"></div>
+        <div style="margin-left: 22px; min-width: 95px" class="phone">
+          
+        </div>
         <div class="button" style="margin-left: 24px">绑定微信</div>
       </div>
       <div style="margin-top: 26px; display: flex; align-items: center">
@@ -542,12 +544,12 @@ const extraList = ref([]);
 const arr = ref([]);
 const extra = async () => {
   try {
-    arr.value = []
+    arr.value = [];
     const { data } = await userApi.extra({});
     extraList.value = data;
     extraList.value.forEach((item) => {
       arr.value.push({
-        [item.column_id]:item.value,
+        [item.column_id]: item.value,
         key: item.column_id,
         label: item.name,
       });
@@ -665,9 +667,16 @@ const save = async () => {
       ...from,
     });
     User.getUser();
-    extra()
-    dialogVisible.value = true;
+    extra();
     reward_integral.value = data.reward_integral;
+    if (reward_integral.value > 0) {
+      dialogVisible.value = true;
+    } else {
+      ElMessage({
+        message: "修改成功",
+        type: "success",
+      });
+    }
   } catch (error) {}
 };
 //防抖

+ 2 - 0
src/views/personal/components/wallet.vue

@@ -187,6 +187,8 @@ const toget = async (id) => {
       type: "success",
     });
     __task__();
+    __topic__();
+    User.getUser();
   } catch (error) {}
 };
 //任务列表

+ 19 - 4
src/views/personal/foot.vue

@@ -17,19 +17,34 @@
           >
             <div>
               <img
-                v-if="child.source.image || child.source.images[0]"
-                :src="child.source.image || child.source.images[0]"
+                v-if="child.source"
+                :src="
+                  child.source && child.source.image
+                    ? child.source.image
+                    : child.source.images
+                    ? child.source.images[0]
+                    : ''
+                "
                 style="width: 230px; height: 132px; object-fit: cover"
                 alt=""
               />
               <div v-else style="width: 230px; height: 132px"></div>
-              <div style="margin-top: 12px; width: 230px">
+              <div
+                v-if="child.source"
+                style="margin-top: 12px; width: 230px;height: 40px;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;"
+                v-html="
+                  child.source.name ||
+                  child.source.title ||
+                  child.source.content
+                "
+              ></div>
+              <!-- <div v-if="child.source" style="margin-top: 12px; width: 230px">
                 {{
                   child.source.name ||
                   child.source.title ||
                   child.source.content
                 }}
-              </div>
+              </div> -->
             </div>
           </div>
         </div>

+ 122 - 32
src/views/personal/index.vue

@@ -20,7 +20,54 @@ import * as delApi from "~/api/forum";
 import * as artivleApi from "~/api/article";
 import * as videoApi from "~/api/video";
 import * as infoApi from "~/api/news";
+import { CaretBottom, Search } from "@element-plus/icons-vue";
 const router = useRouter();
+const subNavCurrent = ref("forum");
+//勋章列表
+const boutiqueList = ref([]);
+const boutique_post = async (id) => {
+  try {
+    const { data } = await follow.badge({
+      code: "boutique_post",
+    });
+    boutiqueList.value = data;
+  } catch (error) {}
+};
+onMounted(boutique_post);
+//点赞勋章
+const likeList = ref([]);
+const like = async (id) => {
+  try {
+    const { data } = await follow.badge({
+      code: "like",
+    });
+    likeList.value = data;
+  } catch (error) {}
+};
+onMounted(like);
+//发帖/回帖勋章
+const postList = ref([]);
+const post = async (id) => {
+  try {
+    const { data } = await follow.badge({
+      code: "post",
+    });
+    postList.value = data;
+  } catch (error) {}
+};
+onMounted(post);
+//拍摄勋章
+const shootList = ref([]);
+const shoot = async (id) => {
+  try {
+    const { data } = await follow.badge({
+      code: "post",
+    });
+    shootList.value = data;
+  } catch (error) {}
+};
+onMounted(shoot);
+
 //删除
 const delect = (id) => {
   if (subNavCurrent.value == "forum") {
@@ -161,9 +208,9 @@ const todetails = (id) => {
       },
     });
   }
-  if (secondSubNavCurrent.value == "goods") {
+  if (secondSubNavCurrent.value == "integral_goods") {
     router.push({
-      name: "PointShoping",
+      path: "/store/pointshoping/:id",
       query: {
         id: id,
       },
@@ -254,10 +301,9 @@ onMounted(__articles__);
 console.log("user see>>", User);
 
 // forum, news, article, video, collect
-const subNavCurrent = ref("forum");
-if (route.query.subNavCurrent) {
-  subNavCurrent.value = "collect";
-}
+// if (route.query.subNavCurrent) {
+//   subNavCurrent.value = "collect";
+// }
 // default value 'forum'
 const subNavList = PERSONAL_SUB_NAV_LIST;
 
@@ -287,7 +333,6 @@ onMounted(__subnav__);
 const handleSwitchSecondSubNav = debounce((type) => {
   if (secondSubNavCurrent.value === type) return;
   secondSubNavCurrent.value = type;
-  console.log("type", type);
   __subnav__();
 }, 240);
 
@@ -325,10 +370,10 @@ const __reset_params__ = () =>
 watchEffect(() => {
   let temporary = {};
   switch (subNavCurrent.value) {
-    case "post":
+    case "forum":
       temporary.source_type = "post";
       break;
-    case "info":
+    case "news":
       temporary.source_type = "info";
       break;
     case "article":
@@ -348,22 +393,22 @@ watchEffect(() => {
     subNavCurrent.value
   );
 
-  // // 收藏接口不走接口
-  // if (subNavCurrent.value === "collect") {
-  //   __subnav__()
-  // } else {
-  //   Object.assign(params, __reset_params__(), temporary);
-  // }
+  // 收藏接口不走接口
+  if (subNavCurrent.value === "collect") {
+    __subnav__();
+  } else {
+    Object.assign(params, __reset_params__(), temporary);
+  }
 });
 
 // onMounted()
 const { tableData, pagination, refrenshTableData } =
   usePersonalIndexList(params);
 
-// const handleRefreshListData = () => {
-//   refrenshTableData();
-//   usePersonalIndexList();
-// };
+const handleRefreshListData = () => {
+  refrenshTableData();
+  usePersonalIndexList();
+};
 //其他用户信息接口
 const __other__ = async (id) => {
   try {
@@ -418,10 +463,14 @@ const other = (id) => {
                   <template #dropdown>
                     <el-dropdown-menu>
                       <el-dropdown-item
-                        >勋章等级:{{
-                          User.boutique_post_level
-                        }}</el-dropdown-item
+                        v-for="(item, idx) in boutiqueList"
+                        :key="idx"
                       >
+                        {{ item.full_name }}
+                        <span style="margin-left: 10px"
+                          >({{ item.complete_time }}/{{ item.times }})
+                        </span>
+                      </el-dropdown-item>
                     </el-dropdown-menu>
                   </template>
                 </el-dropdown>
@@ -436,8 +485,14 @@ const other = (id) => {
                   <template #dropdown>
                     <el-dropdown-menu>
                       <el-dropdown-item
-                        >勋章等级:{{ User.like_level }}</el-dropdown-item
+                        v-for="(item, idx) in likeList"
+                        :key="idx"
                       >
+                        {{ item.full_name }}
+                        <span style="margin-left: 10px"
+                          >({{ item.complete_time }}/{{ item.times }})
+                        </span>
+                      </el-dropdown-item>
                     </el-dropdown-menu>
                   </template>
                 </el-dropdown>
@@ -452,8 +507,14 @@ const other = (id) => {
                   <template #dropdown>
                     <el-dropdown-menu>
                       <el-dropdown-item
-                        >勋章等级:{{ User.post_level }}</el-dropdown-item
+                        v-for="(item, idx) in postList"
+                        :key="idx"
                       >
+                        {{ item.full_name }}
+                        <span style="margin-left: 10px"
+                          >({{ item.complete_time }}/{{ item.times }})
+                        </span>
+                      </el-dropdown-item>
                     </el-dropdown-menu>
                   </template>
                 </el-dropdown>
@@ -468,8 +529,14 @@ const other = (id) => {
                   <template #dropdown>
                     <el-dropdown-menu>
                       <el-dropdown-item
-                        >勋章等级:{{ User.shoot_level }}</el-dropdown-item
+                        v-for="(item, idx) in shootList"
+                        :key="idx"
                       >
+                        {{ item.full_name }}
+                        <span style="margin-left: 10px"
+                          >({{ item.complete_time }}/{{ item.times }})
+                        </span>
+                      </el-dropdown-item>
                     </el-dropdown-menu>
                   </template>
                 </el-dropdown>
@@ -598,7 +665,7 @@ const other = (id) => {
             <template v-for="(item, idx) in subList" :key="idx">
               <div @click="todetails(item.id)" class="lunbox">
                 <img
-                  :src="item.image"
+                  :src="item.images[0] || ''"
                   style="width: 112px; height: 112px"
                   alt=""
                 />
@@ -613,23 +680,33 @@ const other = (id) => {
             </template>
           </div>
           <div
-            v-if="secondSubNavCurrent == 'goods'"
+            v-if="secondSubNavCurrent == 'integral_goods'"
             class="flex-row"
             style="column-gap: 20px; flex-wrap: wrap"
           >
             <template v-for="(item, idx) in subList" :key="idx">
-              <div @click="todetails(item.id)" class="goodsbox" style="margin-bottom: 20px">
+              <div
+                @click="todetails(item.id)"
+                class="goodsbox"
+                style="margin-bottom: 20px"
+              >
                 <img
                   :src="item.image"
                   style="width: 182px; height: 182px"
                   alt=""
                 />
                 <div style="margin-left: 10px">
-                  <div style="margin-top: 14px; text-align: center">
-                    {{ item.title }}
+                  <div
+                    style="margin-top: 14px; text-align: center"
+                    class="name"
+                  >
+                    {{ item.name }}
                   </div>
-                  <div style="margin-top: 10px; text-align: center">
-                    {{ item.integral }}
+                  <div
+                    style="margin-top: 10px; text-align: center"
+                    class="price"
+                  >
+                    {{ item.price }}积分
                   </div>
                 </div>
               </div>
@@ -714,6 +791,19 @@ const other = (id) => {
 
 <style lang="scss" scoped>
 @import "~/styles/variable.scss";
+.name {
+  font-family: PingFangSC, PingFang SC;
+  font-weight: 400;
+  font-size: 12px;
+  color: #444444;
+  line-height: 17px;
+  text-align: justify;
+  font-style: normal;
+  height: 20px;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
 .goodsbox {
   width: 222px;
   height: 276px;

+ 1 - 3
src/views/personal/inviteinfo.vue

@@ -147,9 +147,7 @@ const beforeRemove = (uploadFile, uploadFiles) => {
 };
 
 //上传数据
-const fileList = ref([
-
-]);
+const fileList = ref([]);
 //打开投递简历对话框
 const open = () => {
   centerDialogVisible.value = true;

+ 16 - 1
src/views/personal/make.vue

@@ -76,7 +76,7 @@
               alt=""
             />
           </div>
-          <div class="goto">立即跳转</div>
+          <div class="goto" @click="togo" >立即跳转</div>
         </div>
       </div>
       <div
@@ -217,6 +217,20 @@ import {
   WarningFilled,
   SuccessFilled,
 } from "@element-plus/icons-vue";
+//立即跳转
+const toUrl = ref()
+const shoot = async () => {
+  try {
+    const { data } = await commonApi.getConfig({
+      module: "shoot",
+    });
+    toUrl.value = data.appointment_url
+  } catch (error) {}
+};
+onMounted(shoot)
+const togo = ()=>{
+  window.open(toUrl.value)
+}
 //tabs切换
 const type = ref("");
 const route = useRoute();
@@ -393,6 +407,7 @@ onMounted(() => {});
   line-height: 52px;
   text-align: center;
   font-style: normal;
+  cursor: pointer;
 }
 .content {
   width: 842px;

+ 11 - 4
src/views/postDetail.vue

@@ -108,7 +108,7 @@ const __articlesDetail__ = async () => {
     });
     Object.assign(details, {
       title: data.title,
-      image: data.image, //封面图
+      image: data.images, //封面图
       description: data.description,
       content: data.content, //内容
       status: data.status, //状态: frozen.冻结, normal.正常
@@ -135,7 +135,7 @@ const __videoDetail__ = async () => {
     });
     Object.assign(details, {
       title: data.title,
-      image: data.image, //封面图
+      image: data.images, //封面图
       description: data.description,
       content: data.content, //内容
       status: data.status, //状态: frozen.冻结, normal.正常
@@ -163,7 +163,7 @@ const __posDetail__ = async () => {
     });
     Object.assign(details, {
       title: data.title,
-      image: data.image, //封面图
+      image: data.images, //封面图
       description: data.description,
       content: data.content, //内容
       status: data.status, //状态: frozen.冻结, normal.正常
@@ -345,7 +345,14 @@ console.log("%c route >>>", "background: blue; color: #fff", Route, Route.name);
     </div>
     <div class="tip">本文系用户投稿,不代表忆象网观点</div>
     <div class="post-context" v-html="details.content"></div>
-    <div>{{ details.image }}</div>
+    <div v-if="(detaildType == 'post')">
+      <div v-for="(item, idx) in details.image" :key="idx">
+        <img :src="item" alt="" />
+      </div>
+    </div>
+    <div v-else>
+      <img :src="details.image" alt="">
+    </div>
     <div class="post-footer flex-row flex-aic flex-jc-sb">
       <div class="left">
         <span

+ 134 - 13
src/views/sundry/editor.vue

@@ -18,16 +18,104 @@ import { Plus } from "@element-plus/icons-vue";
 import { useUploadImage } from "~/useHook/useUploadImage";
 import { useCommonStore } from "~/store/index";
 import { usePost } from "~/useHook/usePost";
+import { usePut } from "~/useHook/usepuy";
 import { genFileId } from "element-plus";
-import { useRouter } from "vue-router";
+import { useRouter, useRoute } from "vue-router";
 
+import * as articleApi from "~/api/article";
+
+import * as newsApi from "~/api/news";
+
+import * as videoApi from "~/api/video";
+
+import * as forumApi from "~/api/forum";
 const commonStore = useCommonStore();
 const router = useRouter();
-
+const route = useRoute();
+const currentTopid = ref(0);
+const topicTitle = ref(null);
 // 编辑器实例,必须用 shallowRef
 const editorRef = shallowRef();
 // 内容 HTML
 const valueHtml = ref("<p></p>");
+//文章详情
+const articleInfo = async () => {
+  try {
+    const { data } = await articleApi.info({
+      id: route.query.id,
+    });
+    valueHtml.value = data.content;
+    title.value = data.title;
+    imageCover.value = data.image;
+    currentTopid.value = data.topic_id;
+    topicTitle.value = data.topic.title;
+    // handleCreated()
+    console.log("currentTopid", currentTopid.value);
+  } catch (error) {}
+};
+//资讯详情
+const newsInfo = async () => {
+  try {
+    const { data } = await newsApi.info({
+      id: route.query.id,
+    });
+    valueHtml.value = data.content;
+    title.value = data.title;
+    imageCover.value = data.image;
+    currentTopid.value = data.topic_id;
+    topicTitle.value = data.topic.title;
+    // handleCreated()
+  } catch (error) {}
+};
+//视频详情
+const videoInfo = async () => {
+  try {
+    const { data } = await videoApi.info({
+      id: route.query.id,
+    });
+    valueHtml.value = data.content;
+    title.value = data.title;
+    imageCover.value = data.image;
+    currentTopid.value = data.topic_id;
+    console.log("currentTopid", currentTopid.value);
+    videoTitle.value = data.video_title;
+    videoUrl.value = data.video_url;
+    topicTitle.value = data.topic.title;
+    // handleCreated()
+  } catch (error) {}
+};
+//论坛详情
+const imageCove = ref([]);
+const postInfo = async () => {
+  try {
+    const { data } = await forumApi.info({
+      id: route.query.id,
+    });
+    valueHtml.value = data.content;
+    title.value = data.title;
+    imageCover.value = data.images;
+    currentTopid.value = data.topic_id;
+    topicTitle.value = data.topic.title;
+    // handleCreated()
+  } catch (error) {}
+};
+onMounted(() => {
+  if (route.query.type == "article" && route.query.id) {
+    articleInfo();
+    commonStore.editorType = "article";
+  } else if (route.query.type == "info" && route.query.id) {
+    newsInfo();
+    commonStore.editorType = "news";
+  } else if (route.query.type == "video" && !route.query.id) {
+    commonStore.editorType = "video";
+  } else if (route.query.type == "post" && route.query.id) {
+    postInfo();
+    commonStore.editorType = "forum";
+  } else if (route.query.type == "video" && route.query.id) {
+    videoInfo();
+    commonStore.editorType = "video";
+  }
+});
 
 const toolbarConfig = {
   toolbarKeys: [
@@ -145,6 +233,7 @@ const handleCustomUploadImage = async (options) => {
 
     const { imageFile } = await useUploadImage(formdata);
     if (imageFile.value) imageCover.value = imageFile.value;
+    // if (imageFile.value) imageCove.value = imageCove.value.push(imageFile.value);
     options.onSuccess();
   } catch (error) {
     options.onError();
@@ -168,7 +257,7 @@ const handleRecordMoment = (status) => {
       topic_id: currentTopic.value ? currentTopic.value.id : "0", // default 0 or ''
       status: status,
       image: imageCover.value,
-
+      id: route.query.id,
       // article mode
       // title
       // content
@@ -188,15 +277,33 @@ const handleRecordMoment = (status) => {
     }
 
     try {
-      const result = await usePost(commonStore.editorType, formdata);
+      if (route.query.verdict == 1) {
+        const result = await usePut(commonStore.editorType, formdata);
+      } else {
+        const result = await usePost(commonStore.editorType, formdata);
+      }
+
       ElMessage.success(`${str}成功`);
-      if (commonStore.editorType == "video") {
+      console.log("str", str);
+      if (commonStore.editorType == "video" && str != "存草稿") {
         router.push({
-          path: "video",
+          path: "/video",
         });
-      } else if (commonStore.editorType == "article") {
+      } else if (route.query.type == "article" && str != "存草稿") {
         router.push({
-          path: "articles",
+          path: "/articles",
+        });
+      } else if (route.query.type == "post" && str != "存草稿") {
+        router.push({
+          path: "/forum",
+        });
+      } else if (route.query.type == "info" && str != "存草稿") {
+        router.push({
+          path: "/zixun",
+        });
+      } else if (str == "存草稿") {
+        router.push({
+          path: "/draft",
         });
       }
     } catch (error) {
@@ -204,7 +311,7 @@ const handleRecordMoment = (status) => {
     }
   });
 };
-
+console.log("type", route);
 // 接收话题
 const currentTopic = ref(null);
 const handleReciveTopic = (topic) => {
@@ -224,7 +331,6 @@ const handleReciveTopic = (topic) => {
         />
       </div>
     </div>
-
     <!-- NOTE: 视频模块 -->
     <div class="editor-main videobox" v-if="commonStore.editorType === 'video'">
       <div class="footerbox">
@@ -250,12 +356,16 @@ const handleReciveTopic = (topic) => {
     </div>
     <div class="editor-main">
       <el-input
+        v-if="commonStore.editorType != 'forum'"
         class="inputtitle"
         v-model="title"
         size="large"
         placeholder="请输入标题"
       ></el-input>
-      <div class="editor-main__border"></div>
+      <div
+        v-if="commonStore.editorType != 'forum'"
+        class="editor-main__border"
+      ></div>
       <Editor
         style="height: 500px; overflow-y: hidden"
         v-model="valueHtml"
@@ -281,7 +391,14 @@ const handleReciveTopic = (topic) => {
               :http-request="handleCustomUploadImage"
               :on-remove="handleRemove"
             >
-              <img v-if="imageCover" :src="imageCover" class="image-cover" />
+              <!-- <div v-if="commonStore.editorType == 'forum'">
+                <img :src="imageCove[0]" alt="" class="image-cover" />
+              </div> -->
+              <img
+                v-if="imageCover"
+                :src="imageCover"
+                class="image-cover"
+              />
               <template v-else>
                 <el-icon :size="18" color="#999">
                   <Plus />
@@ -292,7 +409,11 @@ const handleReciveTopic = (topic) => {
             <p class="upload-tip">图片上传格式支持JPEG、PNG</p>
           </el-form-item>
           <el-form-item label="话题选择">
-            <ChooseSubjectToTalk @recive-topic="handleReciveTopic" />
+            <ChooseSubjectToTalk
+              @recive-topic="handleReciveTopic"
+              :Topid="currentTopid"
+              :Title="topicTitle"
+            />
           </el-form-item>
         </el-form>
       </div>

+ 188 - 37
src/views/tongzhi/chat.vue

@@ -2,7 +2,7 @@
 
 <template>
   <div class="articles-container">
-    <div style="background: #fff;  width: 1092px; display: flex">
+    <div style="background: #fff; width: 1092px; display: flex">
       <div style="width: 818px">
         <div
           style="border-bottom: 1px solid #ebebeb; height: 75px; display: flex"
@@ -17,7 +17,7 @@
               justify-content: space-between;
             "
           >
-            <div>
+            <div style="cursor: pointer" @click="returna">
               <img
                 style="width: 22px; height: 22px"
                 src="../../assets/chat/return.png"
@@ -25,36 +25,56 @@
               />
               <span>返回</span>
             </div>
-            <div>诗意天空JX 与你对话</div>
+            <div>{{ username }} 与你对话</div>
             <div>
               <img
-                style="width: 22px; height: 22px"
+                style="width: 22px; height: 22px; cursor: pointer"
                 src="../../assets/chat/report.png"
                 alt=""
               />
             </div>
           </div>
         </div>
-        <div style="height: 499px; padding: 27px 24px">
-          <div style="text-align: center">47分钟前</div>
-          <div>
+        <div
+          ref="scrollDiv"
+          style="
+            height: 499px;
+            padding: 27px 24px;
+            overflow: hidden;
+            overflow-y: scroll;
+          "
+        >
+          <div v-for="(item, idx) in chatinfo" :key="idx">
+            <div style="text-align: center" class="time">
+              {{ item.created_at }}
+            </div>
             <div style="display: flex; justify-content: space-between">
               <div style="display: flex">
                 <img
-                  src="../../assets/logo.png"
+                  v-if="item.is_me == 0"
+                  :src="item.chat_user.avatar"
                   style="width: 36px; height: 36px; border-radius: 50%"
                   alt=""
                 />
-                <div style="margin-left: 14px" class="conten lefta">
-                  周末抽空一起去拍一个VR摄影宣传片吧
+                <div
+                  v-if="item.is_me == 0"
+                  style="margin-left: 14px"
+                  class="conten lefta"
+                >
+                  {{ item.content }}
                 </div>
               </div>
               <div style="display: flex">
-                <div style="margin-right: 14px" class="conten righta">
-                  周末抽空一起去拍一个VR摄影宣传片吧
+                <div
+                  v-if="item.is_me == 1"
+                  style="margin-right: 14px"
+                  class="conten righta"
+                >
+                  {{ item.content }}
                 </div>
                 <img
-                  src="../../assets/logo.png"
+                  v-if="item.is_me == 1"
+                  :src="User.avatar"
                   style="width: 36px; height: 36px; border-radius: 50%"
                   alt=""
                 />
@@ -63,15 +83,34 @@
           </div>
         </div>
         <div
-          style="height: 200px; padding: 24px; border-top: 1px solid #ebebeb;box-sizing: border-box;"
+          style="
+            height: 200px;
+            padding: 24px;
+            border-top: 1px solid #ebebeb;
+            box-sizing: border-box;
+          "
         >
           <div style="display: flex">
-            <img src="../../assets/logo.png" style="width: 30px;height: 30px;border-radius: 50%;margin-right: 14px;" alt="" />
-            <el-input v-model="input" style="width: 720px;
-height: 100px;" placeholder="说点什么呢" />
+            <img
+              :src="User.avatar"
+              style="
+                width: 30px;
+                height: 30px;
+                border-radius: 50%;
+                margin-right: 14px;
+              "
+              alt=""
+            />
+            <el-input
+              :rows="4"
+              type="textarea"
+              v-model="input"
+              style="width: 720px; height: 100px"
+              placeholder="说点什么呢"
+            />
           </div>
-          <div style="display: flex;justify-content: right">
-            <div class="btn" >回复</div>
+          <div style="display: flex; justify-content: right">
+            <div @click="reply" :class="input ? 'btn3' : 'btn'">回复</div>
           </div>
         </div>
       </div>
@@ -85,20 +124,29 @@ height: 100px;" placeholder="说点什么呢" />
         >
           私信列表
         </div>
-        <div class="box">
-          <img
-            style="width: 36px; height: 36px; border-radius: 50%"
-            src="../../assets/logo.png"
-            alt=""
-          />
-          <div style="margin-left: 12px">
-            <div style="display: flex; justify-content: space-between">
-              <div class="namea">诗意天…</div>
-              <div class="timea">09-12 12:17</div>
-            </div>
-            <div style="margin-top: 6px" class="cona">
-              周末抽空一起去拍一个VR摄 影宣传片吧!
+        <div style="overflow-y: scroll; height: 753px">
+          <div
+            @click="chat(item.chat_user.id, item.chat_user.username)"
+            v-for="(item, idx) in list"
+            :key="idx"
+            class="box"
+          >
+            <!-- <template v-if="item.chat_user"> -->
+            <img
+              style="width: 36px; height: 36px; border-radius: 50%"
+              :src="item.chat_user.avatar || ''"
+              alt=""
+            />
+            <div style="margin-left: 12px">
+              <div style="display: flex; justify-content: space-between">
+                <div class="namea">{{ item.chat_user.username }}</div>
+                <div class="timea">{{ item.chat_user.created_at }}</div>
+              </div>
+              <div style="margin-top: 6px" class="cona">
+                {{ item.content }}
+              </div>
             </div>
+            <!-- </template> -->
           </div>
         </div>
       </div>
@@ -106,15 +154,104 @@ height: 100px;" placeholder="说点什么呢" />
   </div>
 </template>
 <script setup>
-import { ref } from "vue";
-//更改
-let changeval = ref("0");
-const change = (val) => {
-  changeval.value = val;
+import { onMounted, ref } from "vue";
+import * as privateApi from "~/api/private";
+import { useRoute, useRouter } from "vue-router";
+import { useUser } from "~/store/user.js";
+const User = useUser();
+const route = useRoute();
+const ida = ref("");
+const input = ref("");
+const chatinfo = ref("");
+const router = useRouter();
+console.log("route.query.id1", route.query.id);
+if (route.query.id) {
+  ida.value = route.query.id;
+  console.log("route.query.id", route.query.id);
+}
+const scrollDiv = ref(null);
+const scrollToBottom = () => {
+  if (scrollDiv.value) {
+    scrollDiv.value.scrollIntoView({ behavior: "smooth" });
+  }
+};
+onMounted(scrollToBottom);
+// 使用方法
+// 返回
+const returna = () => {
+  router.go(-1);
+};
+const detail1 = (id) => {
+  ida.value = id;
+  detail();
+};
+//聊天详情
+const detail = async () => {
+  try {
+    const { data } = await privateApi.chat({
+      is_page: 0,
+      chat_user_id: ida.value,
+    });
+    chatinfo.value = data;
+  } catch (error) {}
+};
+onMounted(detail);
+
+//回复接口
+const multipart = async () => {
+  try {
+    const { data } = await privateApi.multipart({
+      chat_user_id: ida.value,
+      content: input.value,
+    });
+    detail(ida.value);
+    chatList();
+    input.value = "";
+  } catch (error) {}
+};
+//回复
+const reply = () => {
+  if (input.value) {
+    multipart();
+  } else {
+    ElMessage({
+      message: "请填写内容",
+      type: "warning",
+    });
+  }
+};
+//私信列表
+const list = ref();
+const chatList = async () => {
+  try {
+    const { data } = await privateApi.list({
+      is_page: 0,
+    });
+    list.value = data;
+  } catch (error) {}
+};
+onMounted(chatList);
+//私信列表
+const username = ref();
+if (route.query.id) {
+  username.value = route.query.username;
+}
+const chat = (id, name) => {
+  detail1(id);
+  username.value = name;
 };
 </script>
 <style lang="scss" scoped>
 @import "~/styles/variable.scss";
+.time {
+  font-family: PingFangSC, PingFang SC;
+  font-weight: 400;
+  font-size: 12px;
+  color: #999999;
+  line-height: 17px;
+  text-align: justify;
+  font-style: normal;
+}
 .namea {
   font-family: PingFangSC, PingFang SC;
   font-weight: 500;
@@ -196,6 +333,20 @@ const change = (val) => {
   height: 22px;
   background: #00b0b0;
 }
+.btn3 {
+  width: 104px;
+  height: 40px;
+  background: #00b0b0;
+  border-radius: 4px;
+  font-family: PingFangSC, PingFang SC;
+  font-weight: 400;
+  font-size: 14px;
+  color: #ffffff;
+  line-height: 40px;
+  text-align: center;
+  font-style: normal;
+  margin-top: 16px;
+}
 
 .articles-container {
   display: flex;

+ 4 - 3
src/views/tongzhi/components/comment.vue

@@ -26,9 +26,9 @@
         <div>
           <div class="content">{{ item.content }}</div>
           <div style="display: flex;margin-top: 19px;">
-            <div style="cursor: pointer;" @click="like(item.source_id, item.source_type)">
+            <div style="cursor: pointer;" @click="like(item.id, item.source_type)">
               <SvgIcon name="like" :size="16" :rgap="2" :color="item.is_like == 1 ? '#00b0b0' : '#999999'" />
-              <span>赞</span>
+              <span :style="{color:item.is_like == 1 ? '#00b0b0' : '#999999'}">赞</span>
             </div>
             <div @click="todetail(item.source_id, item.source_type)" style="margin-left: 26px;cursor: pointer;">
               <SvgIcon name="message" :size="16" :rgap="2"  />
@@ -64,6 +64,7 @@ import { onMounted, ref } from "vue";
 import * as commentApi from "~/api/comment";
 import { useUser } from "~/store/user";
 import * as gatherApi from "~/api/gather";
+import SvgIcon from "~/components/SvgIcon/index.vue";
 const User = useUser();
 let newsList = ref([]);
 const __news__ = async () => {
@@ -123,7 +124,7 @@ const todetail = (id, type) => {
 const like = async (id,type) => {
   try {
     const { msg } = await gatherApi.like({
-      source_type: type,
+      source_type: 'comment',
       source_id:id,
     });
     ElMessage({

+ 4 - 5
src/views/tongzhi/components/inform.vue

@@ -7,7 +7,7 @@
     </el-tabs>
   </div>
   <div>
-    <template v-if="type == ''">
+    <template v-if="type == 'system'">
       <!-- 全部通知 -->
       <div class="box" v-for="(item, index) in articleList" :key="index">
         <div style="display: flex; align-items: center">
@@ -23,10 +23,9 @@
         class="box"
         style="display: flex"
         v-for="(item, index) in articleList"
-        :key="index"
-      >
-        <div><img src="" style="width: 48px; height: 48px" alt="" /></div>
-        <div>
+        :key="index">
+        <div><img :src="item.image" style="width: 48px; height: 48px;border-radius: 50%;" alt="" /></div>
+        <div style="margin-left: 10px;">
           <div>
             <span class="title">{{ item.title }}</span>
             <span class="data">{{ item.updated_at }}</span>

Някои файлове не бяха показани, защото твърде много файлове са промени