Lijy 5 mēneši atpakaļ
vecāks
revīzija
142bf615c3

+ 14 - 1
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/components/layout/Page.vue

@@ -1,5 +1,5 @@
 <template>
-    <div :class="`page ${!props.title? 'page-no-title':''}`">
+    <div :class="`page ${!props.title? 'page-no-title':''} ${styleReset}`">
         <van-nav-bar class="header"
                      v-bind:title="props.title"
                      v-if="showHeader"
@@ -50,6 +50,13 @@ const props = defineProps({
         type: [String, Number],
         default: 44
     },
+    /**
+     * @property headerHeight {String} 外盒子样式重置
+     * */
+    styleReset: {
+      type: String,
+      default: ''
+    },
     /**
      * @property title {String} 页面顶部标题
      * */
@@ -107,4 +114,10 @@ const goBack = ()=>{
 :deep(.van-nav-bar__content) {
   height: 100% !important;
 }
+
+.headerClass {
+  :deep(.van-nav-bar__content) {
+    background: $themeColor;
+  }
+}
 </style>

+ 11 - 1
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/hooks/useApi.js

@@ -10,4 +10,14 @@ export const GET_CUSTOMER_LIST = '/custom/list' // 获取客户列表
 export const GET_TASK_LIST = '/tasks/pageTask' // 获取任务列表
 export const GET_PRODUCT_LIST = '/product/list' // 获取产品列表
 export const GET_CONTRACT_LIST = '/contract/getContractPage' // 获取合同列表
-export const GET_SALES_ORDER_LIST = '/order/list' // 获取销售订单列表
+export const GET_SALES_ORDER_LIST = '/order/list' // 获取销售订单列表
+
+export const DELETE_BUSINESS_OPPORTUNITY = '/business-opportunity/delete' // 删除商机
+export const DELETE_CLUES = '/clue/delete' // 删除线索
+export const DELETE_CUSTOMER = '/custom/deleter' // 删除客户
+export const DELETE_CONTACTS = '/contacts/deleteContacts' // 删除联系人
+export const DELETE_TASK = '/tasks/deleteTasks' // 删除任务
+export const DELETE_PRODUCT = '/product/delete' // 删除产品
+export const DELETE_CONTRACT = '/contract/deleteContract' // 删除合同
+export const DELETE_ORDER = '/order/delete' // 删除订单
+

+ 1 - 0
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/main.js

@@ -10,6 +10,7 @@ import "@/style.scss";
 import "@/assets/tailwind.css"
 import "vant/es/image-preview/style";
 import "vant/es/toast/style";
+import 'vant/lib/index.css'
 
 const app = createApp(App);
 

+ 43 - 11
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/moduleList/moduleList.vue

@@ -4,7 +4,8 @@
       <div class="flex flex-col h-full">
         <!-- 搜索 -->
         <div class="mx-1">
-          <van-search v-model="searchVal" background="#F8F8F8" :placeholder="`请输入${queryParameters?.name}关键词`">
+          <van-search v-model.trim="searchVal" background="#F8F8F8" :placeholder="`请输入${queryParameters?.name}关键词`"
+            @search="onRefresh(true)" @clear="onRefresh(true)">
             <template v-slot:left-icon>
               <van-icon name="search" class="themeTextColor font-bold" />
             </template>
@@ -12,7 +13,7 @@
         </div>
         <!-- 主题内容 -->
         <div class="flex-1 overflow-y-auto">
-          <template v-if="listData?.records && listData.records.length">
+          <template v-if="listData?.records && listData.records.length && !loadingList">
             <van-pull-refresh v-model="refreshing" @refresh="onRefresh">
               <van-list v-model:loading="isLoading" :finished="finished" finished-text="没有更多了" @load="onLoad">
                 <div v-for="item in listData.records" :key="item.id" @click="toDetail(item)">
@@ -55,12 +56,16 @@
               </van-list>
             </van-pull-refresh>
           </template>
+          <template v-else>
+            <van-skeleton title :row="20" class="w-full h-full" />
+          </template>
         </div>
       </div>
 
       <!-- 可拖拽添加 -->
       <DragBox>
-        <div class="addButton backgroundThemeColor rounded-full flex items-center justify-center text-white" @click="toAddEditor">
+        <div class="addButton backgroundThemeColor rounded-full flex items-center justify-center text-white"
+          @click="toAddEditor()">
           添加
         </div>
       </DragBox>
@@ -70,13 +75,15 @@
 
 <script setup>
 import { ref, onActivated } from 'vue';
+import { showConfirmDialog } from 'vant';
 import { useLifecycle } from '@hooks/useCommon.js';
 import { resetListData, getListFieldKey } from '@components/common/formForm/formCorrespondenceProcessing'
+import useShowToast from '@hooks/useToast'
 import { GET_CUSTOM_FORM_JSON } from '@hooks/useApi'
 import requests from "@common/requests";
 import useRouterStore from "@store/useRouterStore.js";
 import useFixedData from "@store/useFixedData.js"
-import ElementLongPress from "@components/common/elementLongPress.vue";
+// import ElementLongPress from "@components/common/elementLongPress.vue";
 import DragBox from '@components/common/dragBox.vue';
 
 const TRANSFER = 'transfer';
@@ -84,10 +91,12 @@ const DELETE = 'delete';
 const EDIT = 'edit';
 const TOP_MOUNTED = 'topMounted';
 
+const { toastSuccess, toastFail } = useShowToast()
 const router = useRouterStore()
 const fixedData = useFixedData()
 const searchVal = ref()
 const queryParameters = ref()
+const loadingList = ref(false)
 const popUpWindowArray = ref([
   { text: '转移', event: TRANSFER, bg: '#FFA359', removeModule: ['contacts', 'tasks', 'product', 'contract', 'order'] },
   { text: '顶置', event: TOP_MOUNTED, bg: '#075985', removeModule: [] },
@@ -141,7 +150,18 @@ function transfer(row) {
 
 // 删除事件
 function deleteRow(row) {
-  console.log(row, '<======= 删除事件')
+  const { name = '', searchFiled = {}, deteleFiled = '' } = queryParameters.value
+  showConfirmDialog({
+    title: `删除${name}`,
+    message: `确定删除【${row[searchFiled?.search]}】${name}吗?`,
+  }).then(() => {
+    requests.post(deteleFiled, { ids: row.id }).then((res) => {
+      toastSuccess('删除成功')
+      onRefresh(true)
+    }).catch((err) => {
+      toastFail(err.msg ? err.msg : '删除失败')
+    })
+  })
 }
 
 // 顶置事件
@@ -173,11 +193,11 @@ function toAddEditor(value) {
   })
 }
 
-function onRefresh() {
+function onRefresh(flag = false) {
   finished.value = false;
   isLoading.value = true;
   listData.value.pageIndex = 1;
-  fetchListData();
+  fetchListData(flag);
 }
 
 function onLoad() {
@@ -186,7 +206,7 @@ function onLoad() {
   fetchListData()
 }
 
-async function fetchListData() {
+async function fetchListData(flag = false) {
   console.log(listData.value.totalPage, listData.value.pageIndex)
   if (
     // 如果总页数小于等于现页数,并且不是第一次加载, 或者正在加载数据 直接跳出不请求
@@ -196,7 +216,7 @@ async function fetchListData() {
     finished.value = true;
     return;
   }
-  const res = await getListData()
+  const res = await getListData(flag)
   if (res.code === 'ok') {
     const list = res.data.data || res.data.records || res.data.record
     const total = res.data.total
@@ -214,12 +234,20 @@ async function fetchListData() {
   }
 }
 
-async function getListData() {
+async function getListData(flag = false) {
   const url = queryParameters.value.listUrl
+  if (flag) {
+    loadingList.value = true
+  }
   const res = await requests.post(url, {
     pageIndex: listData.value.pageIndex,
     pageSize: listData.value.pageSize,
-    pageFrom: listData.value.pageSize
+    pageFrom: listData.value.pageSize,
+    [queryParameters.value?.searchFiled?.search]: searchVal.value
+  }).finally(() => {
+    if (flag) {
+      loadingList.value = false
+    }
   })
   return res
 }
@@ -265,6 +293,10 @@ useLifecycle({
   width: 37px;
   height: 37px;
   margin-left: 10px;
+
+  &:last-child {
+    margin-right: 10px;
+  }
 }
 
 .addButton {

+ 92 - 4
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/tabbar/home/component/workbench.vue

@@ -1,7 +1,55 @@
 <template>
-  <div>
-    <div class="p-[10px]" v-for="item in 30">
-      工作台
+  <div class="w-full h-full workbench">
+    <!-- 日历 -->
+    <div class="w-full p16 backgroundThemeColor rounded-b-lg">
+      <van-calendar :show-title="false" :show-subtitle="false" :show-mark="false" :poppable="false" :show-confirm="false" :row-height="'2.5rem'"
+        :style="{ height: '45.174vh', borderRadius: '2vw' }" :min-date="minDate" />
+    </div>
+
+    <!-- 日程安排 -->
+    <div class="h-52 overflow-y-auto mt-5">
+      <!-- 有数据的情况 -->
+      <div></div>
+      <!-- 没有数据的情况下 -->
+      <div class="w-full h-full flex flex-col items-center justify-center">
+        <div class="schedulePicture bg-black mb-5"></div>
+        <div class="text-center text-[#C4C4C4] mb-5">您今天还没安排日程哦!</div>
+        <van-button type="primary" class="m-auto w-3/5">马上安排</van-button>
+      </div>
+    </div>
+
+    <!-- 常用表单 -->
+    <div class="mt-5">
+      <div class="text-size-large text-[#000] pl16">常用表单</div>
+      <div class="p16 pt-0 pb-0 flex justify-between overflow-x-auto">
+        <div class="flex">
+          <template v-for="(item, index) in 10">
+            <div class="w80 bg-[#FFA359] h-28 rounded-md flex flex-col items-center justify-center">
+              <div class="formImage"></div>
+              <div class="text-white">表单{{ index }}</div>
+            </div>
+          </template>
+          
+          <div class="w80 bg-[#357AF4] h-28 rounded-md flex flex-col items-center justify-center">
+            <div class="formImage"></div>
+            <div class="text-white">更多</div>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 常用联系人 -->
+    <div class="mt-3">
+      <div class="text-size-large text-[#000] pl16">常用联系人</div>
+      <div class="p16 pt-0 pb-0">
+        <template v-for="item in 10">
+          <div class="flex flex-row items-center rounded-md p-4 bg-white mb-5">
+            <div class="contactImage"></div>
+            <div class="flex-1">张三</div>
+            <div class="rightArrow"></div>
+          </div>
+        </template>
+      </div>
     </div>
   </div>
 </template>
@@ -9,6 +57,9 @@
 <script setup>
 import { ref } from 'vue';
 import { useLifecycle } from '@hooks/useCommon.js';
+import dayjs from 'dayjs';
+
+const minDate = ref(new Date('2024-01-01'))
 
 useLifecycle({
   load: () => {
@@ -18,5 +69,42 @@ useLifecycle({
 </script>
 
 <style lang='scss' scoped>
-  /* 样式代码 */
+.p16 {
+  padding: 16px;
+}
+
+.pl16 {
+  padding-left: 16px;
+}
+
+.w80 {
+  width: 80px;
+  margin-right: 12px;
+}
+
+.formImage {
+  width: 24px;
+  height: 24px;
+  margin-bottom: 12px;
+  background: #000;
+}
+
+.contactImage {
+  width: 29px;
+  height: 29px;
+  border-radius: 50%;
+  background: #000;
+  margin-right: 12px;
+}
+
+.rightArrow {
+  width: 24px;
+  height: 27px;
+  background: #000;
+}
+
+.schedulePicture {
+  width: 48px;
+  height: 51px;
+}
 </style>

+ 85 - 16
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/pages/tabbar/home/index.vue

@@ -1,27 +1,48 @@
 <template>
-  <Page :title="'首页'">
+  <Page styleReset="headerClass">
+    <template v-slot:headerLeft>
+      <div class="text-white">客户管家</div>
+    </template>
     <template v-slot:headerRight>
-      <div @click="showModule = true">新建</div>
+      <div class="newButton" @click="showModule = true">新建</div>
     </template>
 
     <template v-slot:body>
-      <van-tabs v-model:active="homepageType" class="w-full h-full flex flex-col">
-        <van-tab title="工作台" name="workbench" class="w-full h-full">
-          <Workbench />
-        </van-tab>
-        <van-tab title="数据分析" name="dataAnalysis" class="w-full h-full">
-          <DataAnalysis />
-        </van-tab>
-      </van-tabs>
+      <div class="w-full h-full flex flex-col overflow-hidden">
+        <!-- 头部 -->
+        <div class="custom-tabs rounded-b-lg z-10">
+          <div class="custom-tabs-box text-size-in custom-tabs-rad flex items-center overflow-hidden">
+            <div :class="`w-1/2 h-full rounded-r-lg items-justify-center ${homepageType == 'workbench' ? 'themeTextColor bg-white font-bold' : ''}`" @click="homepageType = 'workbench'">工作台</div>
+            <div :class="`w-1/2 h-full rounded-l-lg items-justify-center ${homepageType == 'dataAnalysis' ? 'themeTextColor bg-white font-bold' : ''}`" @click="homepageType = 'dataAnalysis'">数据分析</div>
+          </div>
+        </div>
+        <!-- 内容 -->
+        <div class="flex-1 overflow-y-auto relative aopiuyt">
+          <template v-if="homepageType == 'workbench'">
+            <Workbench />
+          </template>
+          <template v-if="homepageType == 'dataAnalysis'">
+            <DataAnalysis />
+          </template>
+        </div>
+      </div>
+      
+
 
       <!-- 显示对应的模块 -->
-      <van-overlay :show="showModule" class="flex items-center" z-index="100"  @click="showModule = false">
-        <div class="w-3/4 h-3/4 m-auto flex flex-wrap items-center" @click.stop>
-          <div class="text-white w-1/2 text-center" v-for="(item) in moduleList" :key="item.id" @click.stop="toAddEditor(item)">
-            {{ item.name }}
+      <van-popup v-model:show="showModule" closeable position="bottom" round>
+        <div class="newModuleAdded relative">
+          <div class="text-size-large text-[#474A56] absolute topTitle">客户管家</div>
+          <div class="flex flex-wrap">
+            <template v-for="(item) in moduleList" :key="item.id">
+              <div class="w-16 flex flex-col items-center mrSpacing" @click.stop="toAddEditor(item)">
+                <div class="newModuleImage"></div>
+                <div class="mt-3 text-[#474A56]">{{ item.name }}</div>
+              </div>
+            </template>
           </div>
         </div>
-      </van-overlay>
+      </van-popup>
     </template>
 
     <template v-slot:footer>
@@ -61,7 +82,7 @@ function toAddEditor(rows) {
 
 useLifecycle({
   load: () => {
-    
+
   }
 });
 
@@ -73,4 +94,52 @@ useLifecycle({
   flex: 1;
   overflow-y: auto;
 }
+::v-deep .van-tabs__wrap {
+  background-color: $themeColor;
+}
+.newButton {
+  width: 86px;
+  line-height: 30px;
+  background: #fff;
+  color: $themeColor;
+  border-radius: 75px;
+}
+ 
+.custom-tabs {
+  background: $themeColor;
+  padding: 22px 15px;
+  color: #fff;
+}
+
+.custom-tabs-box {
+  width: 100%;
+  border: 1.5px solid #fff; 
+  height: 50px;
+}
+.custom-tabs-rad {
+  border-radius: 6px;
+}
+.aopiuyt {
+  margin-top: -6px;
+}
+.newModuleAdded {
+  padding: 45px 25px 45px 25px;
+}
+
+.newModuleImage {
+  width: 50px;
+  height: 50px;
+  border-radius: 10px;
+  background: #000;
+}
+.mrSpacing {
+  margin-top: 16px;
+  margin-right: 33px;
+  &:nth-child(4n) {
+    margin-right: 0;
+  }
+}
+.topTitle {
+  top: 14px;
+}
 </style>

+ 19 - 3
fhKeeper/formulahousekeeper/customerBuler-crm-h5/src/utility/generalVariables.js

@@ -1,4 +1,4 @@
-import { GET_A_LIST_OF_BUSINESS_OPPORTUNITIES, GET_A_LIST_OF_CLUES, GET_CONTACT_LIST, GET_CUSTOMER_LIST, GET_TASK_LIST, GET_CONTRACT_LIST, GET_SALES_ORDER_LIST, GET_PRODUCT_LIST } from '@hooks/useApi'
+import { GET_A_LIST_OF_BUSINESS_OPPORTUNITIES, GET_A_LIST_OF_CLUES, GET_CONTACT_LIST, GET_CUSTOMER_LIST, GET_TASK_LIST, GET_CONTRACT_LIST, GET_SALES_ORDER_LIST, GET_PRODUCT_LIST, DELETE_BUSINESS_OPPORTUNITY, DELETE_CLUES, DELETE_CUSTOMER, DELETE_CONTACTS, DELETE_TASK, DELETE_PRODUCT, DELETE_CONTRACT, DELETE_ORDER } from '@hooks/useApi'
 
 export const routingInfos = {
   'business': {
@@ -6,6 +6,8 @@ export const routingInfos = {
     key: 'business', // 唯一标识
     icon: 'icon-shangpin', // 图标
     listUrl: GET_A_LIST_OF_BUSINESS_OPPORTUNITIES, // 列表请求接口
+    deteleFiled: DELETE_BUSINESS_OPPORTUNITY, // 删除请求接口和字段
+    searchFiled: { search: 'name' },
     image: '', // 图片
   },
   'thread': {
@@ -13,6 +15,8 @@ export const routingInfos = {
     key: 'thread', // 唯一标识
     icon: 'icon-shangpin',
     listUrl: GET_A_LIST_OF_CLUES,
+    deteleUrl: DELETE_CLUES,
+    searchFiled: { search: 'clueName' },
     image: '',
   },
   'customer': {
@@ -20,6 +24,8 @@ export const routingInfos = {
     key: 'customer', // 唯一标识
     icon: 'icon-shangpin',
     listUrl: GET_CUSTOMER_LIST,
+    deteleFiled: DELETE_CUSTOMER,
+    searchFiled: { search: 'customName' },
     image: '',
   },
   'contacts': {
@@ -27,6 +33,8 @@ export const routingInfos = {
     key: 'contacts', // 唯一标识
     icon: 'icon-shangpin',
     listUrl: GET_CONTACT_LIST,
+    deteleFiled: DELETE_CONTACTS,
+    searchFiled: { search: 'name' },
     image: '',
   },
   'tasks': {
@@ -34,20 +42,26 @@ export const routingInfos = {
     key: 'tasks', // 唯一标识
     icon: 'icon-shangpin',
     listUrl: GET_TASK_LIST,
+    deteleFiled: DELETE_TASK,
+    searchFiled: { search: 'taskName' },
     image: '',
   },
   'product': {
-    name: '产品管理',
+    name: '产品',
     key: 'product', // 唯一标识
     icon: 'icon-shangpin',
     listUrl: GET_PRODUCT_LIST,
+    deteleFiled: DELETE_PRODUCT,
+    searchFiled: { search: 'productName' },
     image: '',
   },
   'contract': {
-    name: '合同管理',
+    name: '合同',
     key: 'contract', // 唯一标识
     icon: 'icon-shangpin',
     listUrl: GET_CONTRACT_LIST,
+    deteleFiled: DELETE_CONTRACT,
+    searchFiled: { search: 'name' },
     image: '',
   },
   'order': {
@@ -55,6 +69,8 @@ export const routingInfos = {
     key: 'order', // 唯一标识
     icon: 'icon-shangpin',
     listUrl: GET_SALES_ORDER_LIST,
+    deteleFiled: DELETE_ORDER,
+    searchFiled: { search: 'orderName' },
     image: '',
   }
 }