Procházet zdrojové kódy

📦 我的投稿列表和登录错误修复

imengyu před 1 měsícem
rodič
revize
4508637220

+ 40 - 0
src/api/user/ContributeApi.ts

@@ -0,0 +1,40 @@
+import { DataModel, transformArrayDataModel } from '@imengyu/js-request-transform';
+import { AppServerRequestModule } from '../RequestModules';
+import { GetContentListItem } from '../CommonContent';
+
+export class ContributeItem extends DataModel<ContributeItem> {
+  constructor() {
+    super(ContributeItem, "投稿");
+    this.setNameMapperCase('Camel', 'Snake');
+    this._convertTable = {
+      id: { clientSide: 'number', serverSide: 'number', clientSideRequired: true },
+    }
+    this._nameMapperServer = {
+    };
+  }
+  modelId = 0;
+  mainBodyColumnId = 0;
+  title = '';
+  type = 1;	//内容类型 :1=文章,2=音频,3=视频,4=相册
+  content = '';
+}
+
+export class ContributeApi extends AppServerRequestModule<DataModel> {
+
+  constructor() {
+    super();
+  }
+
+  async getContributeList(page: number, pageSize: number) {
+    return (this.get('/content/main_body_user/getUserContribute', '用户投稿列表', {
+      page, pageSize,
+    })) 
+      .then(res => transformArrayDataModel<GetContentListItem>(GetContentListItem, res.data2, `用户投稿列表`, true))
+      .catch(e => { throw e });
+  }
+  async contribute(data: ContributeItem) {
+    return (this.post('/content/content/contribute', data, '投稿'));
+  }
+}
+
+export default new ContributeApi();

+ 4 - 0
src/common/components/form/SimpleDynamicFormUni.vue

@@ -35,6 +35,10 @@ const props = defineProps({
     type: Object,
     default: () => ({})
   },
+  formModelInit: {
+    type: Function,
+    default: () => ({})
+  },
 });
 
 const formRef = ref<any>();

+ 1 - 1
src/common/composeabe/RequireLogin.ts

@@ -14,7 +14,7 @@ export function useReqireLogin() {
           confirmText: '去登录' 
         }).then((res) => {
           if (res) {
-            navTo('user/login');
+            navTo('/pages/user/login');
             return;
           }
         })

+ 13 - 0
src/pages.json

@@ -179,6 +179,19 @@
         "navigationBarTitleText": "登录",
         "enablePullDownRefresh": false
       }
+    },
+    {
+      "path": "pages/user/contribute/list",
+      "style": {
+        "navigationBarTitleText": "我的投稿",
+        "enablePullDownRefresh": true
+      }
+    },
+    {
+      "path": "pages/user/contribute/submit",
+      "style": {
+        "navigationBarTitleText": "投稿"
+      }
     }
   ],
   "globalStyle": {

+ 63 - 0
src/pages/user/contribute/list.vue

@@ -0,0 +1,63 @@
+<template>
+  <view class="d-flex flex-column bg-base" style="min-height:100vh">
+    <view class="p-3">
+      <uni-search-bar 
+        v-model="searchText"
+        radius="100"
+        bgColor="#fff"
+        placeholder="搜一搜" 
+        clearButton="auto"
+        cancelButton="none"
+        @confirm="search"
+      />
+    </view>
+    <view class="d-flex flex-column p-3">
+      <Box2LineImageRightShadow 
+        v-for="item in listLoader.list.value"
+        :key="item.id" 
+        classNames="ml-2 mb-3"
+        titleColor="title-text"
+        :image="item.thumbnail || item.image"
+        :title="item.title"
+        :tags="item.keywords"
+        :desc="item.desc"
+        @click="goDetail(item.id)"
+      />
+    </view>
+    <SimplePageListLoader :loader="listLoader" />
+  </view>
+</template>
+
+<script setup lang="ts">
+import { GetContentListItem } from '@/api/CommonContent';
+import SimplePageListLoader from '@/common/components/SimplePageListLoader.vue';
+import { useSimplePageListLoader } from '@/common/composeabe/SimplePageListLoader';
+import { ref } from 'vue';
+import { navTo } from '@/common/utils/PageAction';
+import { onLoad } from '@dcloudio/uni-app';
+import ContributeApi from '@/api/user/ContributeApi';
+import Box2LineImageRightShadow from '@/pages/parts/Box2LineImageRightShadow.vue';
+
+const searchText = ref('');
+const listLoader = useSimplePageListLoader<GetContentListItem>(
+  8, 
+  async (page, pageSize, params) => {
+  return await ContributeApi.getContributeList(page, pageSize);
+});
+
+function goDetail(id: number) {
+  navTo('/pages/article/details', { id });
+}
+function search() {
+  listLoader.loadData(undefined, true);
+}
+onLoad(() => {
+  listLoader.loadData()
+})
+</script>
+
+<style lang="scss">
+.article_list {
+  padding: 20rpx;
+}
+</style>

+ 181 - 0
src/pages/user/contribute/submit.vue

@@ -0,0 +1,181 @@
+<template>
+  <view class="d-flex flex-column bg-base">
+    <u-loading-page :loading="loading" /> 
+    <SimpleDynamicFormUni
+      ref="formRef"
+      :formDefine="formDefine"
+      :formProps="{
+        labelPosition: 'top',
+        labelWidth: '175',
+      }"
+      :formModelInit="formModelInit"
+    />
+    <u-button type="primary" @click="submit">提交</u-button>
+    <u-safe-bottom />
+  </view>
+</template>
+
+<script setup lang="ts">
+import ContributeApi, { ContributeItem } from '@/api/user/ContributeApi';
+import CheckUtils from '@/common/utils/CheckUtils';
+import { showError } from '@/common/composeabe/ErrorDisplay';
+import { ref } from 'vue';
+import type { FormDefine, FormExport } from '@/common/components/form';
+import type { DynamicSelectProps } from '@/common/components/form/components/DynamicSelect.vue';
+import SimpleDynamicFormUni from '@/common/components/form/SimpleDynamicFormUni.vue';
+
+const loading = ref(false);
+
+const formRef = ref<FormExport>();
+const formDefine : FormDefine = {
+  items: [
+    {
+      name: '',
+      children: {
+        type: 'group',
+        props: {
+          class: 'form-block',
+        },
+        propNestType: 'nest', 
+        items: [
+          { 
+            label: '认领村庄', 
+            name: 'village_id',
+            type: 'dynamic-select', 
+            params: {
+              loadData: async () => 
+              (await ContributeApi.getCanClaimVallageList())
+                .map((p) => ({
+                  value: p.id,
+                  text: p.villageName,
+                }))
+              ,
+            } as DynamicSelectProps,
+            rules: [{
+              required: true,
+              errorMessage: '请选择要认领的村庄',
+            }],
+          },
+          { 
+            label: '姓名', 
+            name: 'name', 
+            type: 'text', 
+            defaultValue: '',
+            params: {
+              placeholder: '请输入姓名',
+            },
+            rules:  [{
+              required: true,
+              errorMessage: '请输入姓名',
+            }] 
+          },
+          { 
+            label: '性别', 
+            name: 'sex', 
+            type: 'select', 
+            params: {
+              localdata: [
+                { value: 1, text: "男" },
+                { value: 2, text: "女" },
+                { value: 3, text: "不透露" },
+              ],
+              clear: false,
+            },
+            rules: [{
+              required: true,
+              errorMessage: '请选择性别',
+            }]
+          },
+          {
+            label: '联系方式',
+            name: 'mobile',
+            type: 'text', 
+            defaultValue: '',
+            params: {
+              placeholder: '请输入联系方式',
+            },
+            rules:  [{
+              required: true,
+              errorMessage: '请输入手机号',
+            },{
+              required: true,
+              validateFunction: (rule: any, value: any,data: any,callback: (e: any) => void) => {
+                if (!CheckUtils.checkIsChinesePhoneNumber(value)) {
+                  callback('手机号格式不正确')
+                  return false
+                }
+                return true
+              }
+            }]
+          },
+          {
+            label: '地址',
+            name: 'address',
+            type: 'text', 
+            defaultValue: '',
+            params: {
+              placeholder: '请输入地址',
+            },
+            rules: [{
+              required: true,
+              errorMessage: '请输入地址',
+            }]
+          },
+        ]
+      }
+    },
+    {
+      name: '',
+      children: {
+        type: 'group',
+        props: {
+          class: 'form-block',
+        },
+        propNestType: 'nest', 
+        items: [
+          {
+            label: '申请理由',
+            name: 'claim_reason',
+            type: 'textarea',
+            defaultValue: '',
+            params: {
+              placeholder: '请输入申请理由',
+            },
+            rules: [{
+              required: true,
+              errorMessage: '请输入申请理由',
+            }]
+          }
+        ]
+      }
+    },
+  ]
+}
+
+function formModelInit() {
+  return new ContributeItem();
+}
+
+async function submit() {
+  if (!formRef.value)
+    return;
+  try {
+    const data = await formRef.value.submitForm<ContributeItem>();
+    if (!data)
+      return;
+    loading.value = true;
+    await ContributeApi.contribute(data);
+    uni.showModal({
+      title: '提交成功',
+      content: '感谢您的投稿,我们将尽快审核并通知您结果。',
+    });
+  } catch (e) {
+    showError(e);
+  } finally {
+    loading.value = false;
+  }
+}
+</script>
+
+<style lang="scss">
+</style>

+ 22 - 6
src/pages/user/index.vue

@@ -49,27 +49,27 @@
             <text class="label">我的收藏</text>
             <text class="iconfont icon-arrow-right"></text>
           </view> -->
-          <view class="entry">
+          <!-- <view class="entry" @click="goContribute">
             <image src="https://mn.wenlvti.net/uploads/20250313/07f750b4cf4959654c40171fdae91c3a.png" mode="aspectFill"></image>
             <text class="label">投稿</text>
             <view class="btn">去投稿</view><text class="iconfont icon-arrow-right"></text>
-          </view>
-          <view class="entry">
+          </view> -->
+          <view class="entry" @click="goContributeList">
             <image src="https://mn.wenlvti.net/uploads/20250313/66d4665b1da5075e60148312469b2630.png" mode="aspectFill"></image>
             <text class="label">我的投稿</text>
             <text class="iconfont icon-arrow-right"></text>
           </view>
-          <view class="entry">
+         <!--  <view class="entry">
             <image src="https://mn.wenlvti.net/uploads/20250313/acd97ca7b3f7736942495c7aec1dd65b.png" mode="aspectFill"></image>
             <text class="label">加入我们</text>
             <text class="iconfont icon-arrow-right"></text>
           </view>
-          <!-- <view class="entry">
+          <view class="entry">
             <image src="https://mn.wenlvti.net/uploads/20250313/d2e9010323d098aa51e268fc32f14d3d.png" mode="aspectFill"></image>
             <text class="label">我的预约</text>
             <text class="iconfont icon-arrow-right"></text>
           </view> -->
-          <view class="entry">
+          <view class="entry" @click="showService">
             <image src="https://mn.wenlvti.net/uploads/20250313/d2e9010323d098aa51e268fc32f14d3d.png" mode="aspectFill"></image>
             <text class="label">在线客服</text>
             <text class="iconfont icon-arrow-right"></text>
@@ -93,9 +93,11 @@ import { confirm } from '@/common/utils/DialogAction';
 import { navTo } from '@/common/utils/PageAction';
 import { useAuthStore } from '@/store/auth';
 import { computed } from 'vue';
+import { useReqireLogin } from '@/common/composeabe/RequireLogin';
 
 const authStore = useAuthStore();
 const userInfo = computed(() => authStore.userInfo);
+const { requireLogin } = useReqireLogin();
 
 function doLogout() {
   confirm({
@@ -105,6 +107,20 @@ function doLogout() {
       authStore.logout();
   });
 }
+function goContributeList() {
+  requireLogin(() => navTo('contribute/list'), '登录后才能投稿哦!');
+}
+function goContribute() {
+  requireLogin(() => navTo('contribute/submit'), '登录后才能投稿哦!');
+}
+function showService() {
+  uni.showModal({
+    title: '联系客服',
+    content: '联系电话:18888888888',
+  });
+}
+
+
 </script>
 
 <style lang="scss" scoped>

+ 1 - 1
src/store/auth.ts

@@ -57,7 +57,7 @@ export const useAuthStore = defineStore('auth', {
     },
     async loginResultHandle(loginResult: LoginResult) {
       this.token = loginResult.auth.token;
-      this.userId = loginResult.auth.userId;
+      this.userId = loginResult.mainBodyUserInfo.id;
       this.userInfo = loginResult.mainBodyUserInfo;
       this.expireAt = loginResult.auth.expiresIn + Date.now();