From 3ea1ff641e1c680a5a1727fb4034797bfe65d93e Mon Sep 17 00:00:00 2001
From: spring <2396852758@qq.com>
Date: 星期三, 18 三月 2026 15:29:17 +0800
Subject: [PATCH] fix: 质量、耗材物流

---
 src/pages/qualityManagement/nonconformingManagement/index.vue |  457 +++++++++++++++++++++++++++++++++++---------------------
 1 files changed, 285 insertions(+), 172 deletions(-)

diff --git a/src/pages/qualityManagement/nonconformingManagement/index.vue b/src/pages/qualityManagement/nonconformingManagement/index.vue
index 5efa7ae..f3cc42e 100644
--- a/src/pages/qualityManagement/nonconformingManagement/index.vue
+++ b/src/pages/qualityManagement/nonconformingManagement/index.vue
@@ -2,74 +2,69 @@
   <view class="nonconforming-management-page">
     <PageHeader title="涓嶅悎鏍煎搧绠$悊" @back="goBack" />
     
-    <!-- 鎼滅储涓庣瓫閫� -->
+    <!-- 鎼滅储涓庣瓫閫夛紙鏍峰紡鍙傜収浠撳偍鐗╂祦妯″潡锛� -->
     <view class="search-section">
-      <up-search
-        placeholder="璇疯緭鍏ヤ骇鍝佸悕绉版悳绱�"
-        v-model="searchForm.productName"
-        @search="handleQuery"
-        @custom="handleQuery"
-        @clear="handleQuery"
-        :show-action="true"
-        action-text="鎼滅储"
-        :animation="true"
-        customStyle="margin-bottom: 20rpx"
-      ></up-search>
+      <view class="search-row">
+        <view class="search-input-wrap">
+          <up-input v-model="searchForm.productName" placeholder="浜у搧鍚嶇О" clearable />
+        </view>
+        <view class="btn-search" @click="handleQuery">
+          <view class="btn-search-inner">
+            <up-icon name="search" size="22" color="#fff"></up-icon>
+            <text>鎼滅储</text>
+          </view>
+        </view>
+      </view>
       <view class="filter-row">
         <view class="filter-item" @click="showTypeSelect = true">
           <text>{{ typeLabel }}</text>
           <up-icon name="arrow-down" size="14" color="#999"></up-icon>
         </view>
-        <view class="filter-item" @click="showStatusSelect = true">
-          <text>{{ statusLabel }}</text>
-          <up-icon name="arrow-down" size="14" color="#999"></up-icon>
+        <view class="filter-item" @click="openDateRange">
+          <text>{{ dateRangeLabel }}</text>
+          <up-icon name="calendar" size="14" color="#999"></up-icon>
         </view>
       </view>
     </view>
 
     <!-- 鍒楄〃鍖哄煙 -->
-    <view class="list-container" v-if="tableData.length > 0">
-      <view v-for="(item, index) in tableData" :key="index" class="list-item">
-        <view class="item-header">
-          <text class="product-name">{{ item.productName }}</text>
-          <up-tag :text="getStatusText(item.inspectState)" :type="getStatusType(item.inspectState)" size="mini"></up-tag>
-        </view>
-        <view class="item-content">
-          <view class="item-row">
-            <text class="item-label">绫诲埆锛�</text>
-            <text class="item-value">{{ getInspectTypeText(item.inspectType) }}</text>
+    <view class="list-section">
+      <view v-if="tableData.length > 0">
+        <view v-for="(item, index) in tableData" :key="item.id || index" class="card-item">
+          <view class="card-click" @click="openForm('edit', item)">
+            <view class="card-header">
+              <view class="header-main">
+                <text class="product-name">{{ item.productName }}</text>
+              </view>
+              <view class="header-sub">
+                <text class="sub-title">{{ item.model || '-' }}</text>
+                <up-tag :text="getInspectTypeText(item.checkType ?? item.inspectType)" type="primary" size="mini" />
+              </view>
+            </view>
+            <up-divider />
+            <view class="card-body">
+              <view class="row"><text class="l">妫�娴嬫棩鏈�</text><text class="r">{{ item.checkTime || '-' }}</text></view>
+              <view class="row"><text class="l">鎵瑰彿</text><text class="r">{{ item.batchNo || '-' }}</text></view>
+              <view class="row"><text class="l">妫�楠屽憳</text><text class="r">{{ item.checkName || '-' }}</text></view>
+              <view class="row"><text class="l">涓嶅悎鏍肩幇璞�</text><text class="r text-error">{{ item.defectivePhenomena || '-' }}</text></view>
+              <view class="row" v-if="item.inspectState == 1"><text class="l">澶勭悊缁撴灉</text><text class="r text-success">{{ getDealResultLabel(item.dealResult) || item.dealResult || '-' }}</text></view>
+              <view class="row" v-if="item.inspectState == 1"><text class="l">澶勭悊浜�</text><text class="r">{{ item.dealName || '-' }}</text></view>
+              <view class="row" v-if="item.inspectState == 1"><text class="l">澶勭悊鏃ユ湡</text><text class="r">{{ item.dealTime || '-' }}</text></view>
+            </view>
           </view>
-          <view class="item-row">
-            <text class="item-label">妫�娴嬫棩鏈燂細</text>
-            <text class="item-value">{{ item.checkTime || '-' }}</text>
-          </view>
-          <view class="item-row">
-            <text class="item-label">瑙勬牸鍨嬪彿锛�</text>
-            <text class="item-value">{{ item.model || '-' }}</text>
-          </view>
-          <view class="item-row">
-            <text class="item-label">涓嶅悎鏍肩幇璞★細</text>
-            <text class="item-value text-error">{{ item.defectivePhenomena || '-' }}</text>
-          </view>
-          <view class="item-row" v-if="item.inspectState === 1">
-            <text class="item-label">澶勭悊缁撴灉锛�</text>
-            <text class="item-value text-success">{{ item.dealResult || '-' }}</text>
+          <view class="card-actions">
+            <view class="btn-link btn-link-primary" v-if="item.inspectState == 0" @click.stop="openDealDialog(item)">澶勭悊</view>
+            <view class="btn-link btn-link-plain" v-if="item.inspectState == 0" @click.stop="openForm('edit', item)">缂栬緫</view>
+            <view class="btn-link btn-link-warn" @click.stop="handleDelete(item)">鍒犻櫎</view>
           </view>
         </view>
-        <view class="item-actions">
-          <up-button v-if="item.inspectState === 0" type="primary" size="mini" @click.stop="openDealDialog(item)">澶勭悊</up-button>
-          <up-button type="error" size="mini" @click.stop="handleDelete(item)">鍒犻櫎</up-button>
+        <view class="load-more-wrap">
+          <u-loadmore :status="loadStatus" @loadmore="loadMore" />
         </view>
       </view>
-      <view class="pagination-container">
-        <up-loadmore :status="loadStatus" @loadmore="getList" />
-      </view>
+      <view v-else class="no-data">鏆傛棤鏁版嵁</view>
     </view>
     
-    <view v-else class="no-data">
-      <up-empty mode="data" text="鏆傛棤鏁版嵁"></up-empty>
-    </view>
-
     <!-- 绫诲瀷閫夋嫨鍣� -->
     <up-action-sheet
       :actions="typeActions"
@@ -77,15 +72,6 @@
       @close="showTypeSelect = false"
       @select="selectType"
       title="璇烽�夋嫨绫诲埆"
-    ></up-action-sheet>
-
-    <!-- 鐘舵�侀�夋嫨鍣� -->
-    <up-action-sheet
-      :actions="statusActions"
-      :show="showStatusSelect"
-      @close="showStatusSelect = false"
-      @select="selectStatus"
-      title="璇烽�夋嫨鐘舵��"
     ></up-action-sheet>
 
     <!-- 澶勭悊寮圭獥 -->
@@ -97,10 +83,19 @@
         <up-form :model="dealForm" ref="dealFormRef" label-width="100" label-position="top">
           <view class="info-summary">
             <text class="summary-text">浜у搧锛歿{ currentItem?.productName }}</text>
-            <text class="summary-text">涓嶅悎鏍肩幇璞★細{{ currentItem?.defectivePhenomena }}</text>
+            <text class="summary-text">妫�娴嬫棩鏈燂細{{ currentItem?.checkTime || '-' }}</text>
           </view>
+          <up-form-item label="涓嶅悎鏍肩幇璞�" prop="defectivePhenomena" required borderBottom>
+            <up-textarea v-model="dealForm.defectivePhenomena" placeholder="璇疯緭鍏ヤ笉鍚堟牸鐜拌薄" count border="surround" />
+          </up-form-item>
           <up-form-item label="澶勭悊缁撴灉" prop="dealResult" required borderBottom>
-            <up-textarea v-model="dealForm.dealResult" placeholder="璇疯緭鍏ュ鐞嗙粨鏋�" count border="surround" />
+            <view class="selector-trigger" @click="showDealResultSelect = true">
+              <text class="selector-text" :class="{ placeholder: !dealResultLabel }">{{ dealResultLabel || '璇烽�夋嫨澶勭悊缁撴灉' }}</text>
+              <up-icon name="arrow-down" size="14" color="#999"></up-icon>
+            </view>
+          </up-form-item>
+          <up-form-item label="澶勭悊浜�" prop="dealName" required borderBottom>
+            <up-input v-model="dealForm.dealName" placeholder="璇疯緭鍏ュ鐞嗕汉" border="surround" />
           </up-form-item>
           <up-form-item label="澶勭悊鏃ユ湡" prop="dealTime" required borderBottom>
             <up-input
@@ -119,6 +114,15 @@
       </view>
     </up-popup>
 
+    <!-- 澶勭悊缁撴灉閫夋嫨鍣� -->
+    <up-action-sheet
+      :actions="dealResultActions"
+      :show="showDealResultSelect"
+      @close="showDealResultSelect = false"
+      @select="selectDealResult"
+      title="璇烽�夋嫨澶勭悊缁撴灉"
+    />
+
     <!-- 鏃ユ湡閫夋嫨鍣� -->
     <up-datetime-picker
       :show="showDatePicker"
@@ -127,23 +131,49 @@
       @confirm="confirmDate"
       @cancel="showDatePicker = false"
     ></up-datetime-picker>
+
+    <!-- 褰曞叆鏃ユ湡鑼冨洿閫夋嫨锛氬紑濮� -->
+    <up-datetime-picker
+      :show="showEntryStartPicker"
+      v-model="entryStartValue"
+      mode="date"
+      @confirm="confirmEntryStart"
+      @cancel="showEntryStartPicker = false"
+    />
+    <!-- 褰曞叆鏃ユ湡鑼冨洿閫夋嫨锛氱粨鏉� -->
+    <up-datetime-picker
+      :show="showEntryEndPicker"
+      v-model="entryEndValue"
+      mode="date"
+      @confirm="confirmEntryEnd"
+      @cancel="showEntryEndPicker = false"
+    />
+
+    <!-- 鍙充笅瑙掓柊澧炴寜閽� -->
+    <view class="fab-button" @click="openForm('add')">
+      <up-icon name="plus" size="24" color="#ffffff"></up-icon>
+    </view>
   </view>
 </template>
 
 <script setup>
-import { ref, reactive, onMounted, computed } from 'vue';
+import { ref, reactive, computed } from 'vue';
 import {
   qualityUnqualifiedListPage,
   qualityUnqualifiedDeal,
   qualityUnqualifiedDel
 } from '@/api/qualityManagement/nonconformingManagement.js';
 import { toast, showConfirm } from '@/utils/common';
+import { useDict } from '@/utils/dict'
 import dayjs from 'dayjs';
+import PageHeader from '@/components/PageHeader.vue'
+import { onReachBottom, onShow } from '@dcloudio/uni-app'
 
 const searchForm = reactive({
   productName: '',
-  inspectType: '',
-  inspectState: ''
+  checkType: '',
+  entryDateStart: undefined,
+  entryDateEnd: undefined
 });
 
 const tableData = ref([]);
@@ -162,54 +192,67 @@
   { name: '鍑哄巶妫�', value: '2' }
 ];
 const typeLabel = computed(() => {
-  const action = typeActions.find(a => a.value === searchForm.inspectType);
+  const action = typeActions.find(a => a.value === String(searchForm.checkType ?? ''));
   return action ? action.name : '鍏ㄩ儴绫诲埆';
 });
 
-const showStatusSelect = ref(false);
-const statusActions = [
-  { name: '鍏ㄩ儴', value: '' },
-  { name: '寰呭鐞�', value: '0' },
-  { name: '宸插鐞�', value: '1' }
-];
-const statusLabel = computed(() => {
-  const action = statusActions.find(a => a.value === searchForm.inspectState);
-  return action ? action.name : '鍏ㄩ儴鐘舵��';
-});
+const dateRangeLabel = computed(() => {
+  if (searchForm.entryDateStart && searchForm.entryDateEnd) return `${searchForm.entryDateStart}~${searchForm.entryDateEnd}`
+  if (searchForm.entryDateStart) return `${searchForm.entryDateStart}~`
+  if (searchForm.entryDateEnd) return `~${searchForm.entryDateEnd}`
+  return '妫�娴嬫棩鏈�'
+})
 
 const dealDialogVisible = ref(false);
 const submitLoading = ref(false);
 const currentItem = ref(null);
 const dealForm = reactive({
   id: null,
+  defectivePhenomena: '',
   dealResult: '',
+  dealName: '',
   dealTime: dayjs().format('YYYY-MM-DD')
 });
+
+const { rejection_handling } = useDict('rejection_handling')
+const showDealResultSelect = ref(false)
+const dealResultActions = computed(() => {
+  const list = rejection_handling?.value || []
+  return (list || []).map(it => ({ name: it.label, value: it.value }))
+})
+const dealResultLabel = computed(() => {
+  const list = rejection_handling?.value || []
+  const v = dealForm.dealResult
+  return (list || []).find(it => String(it.value) === String(v))?.label || ''
+})
+function getDealResultLabel(value) {
+  const list = rejection_handling?.value || []
+  return (list || []).find(it => String(it.value) === String(value))?.label || ''
+}
 
 const showDatePicker = ref(false);
 const dateValue = ref(Number(new Date()));
 
+const showEntryStartPicker = ref(false)
+const showEntryEndPicker = ref(false)
+const entryStartValue = ref(Date.now())
+const entryEndValue = ref(Date.now())
+
 const getInspectTypeText = (type) => {
   const types = { '0': '鍏ュ巶妫�', '1': '杞﹂棿妫�', '2': '鍑哄巶妫�' };
-  return types[type] || '-';
-};
-
-const getStatusText = (state) => {
-  return state === 1 ? '宸插鐞�' : '寰呭鐞�';
-};
-
-const getStatusType = (state) => {
-  return state === 1 ? 'success' : 'warning';
+  return types[String(type ?? '')] || '-';
 };
 
 const getList = () => {
-  if (loadStatus.value === 'loading' || (page.total > 0 && tableData.value.length >= page.total)) return;
-  
-  loadStatus.value = 'loading';
+  const isFirstPage = page.current === 1
+  if (loadStatus.value === 'loading' || (!isFirstPage && page.total > 0 && tableData.value.length >= page.total)) return
+
+  loadStatus.value = 'loading'
   const params = {
     productName: searchForm.productName || null,
-    inspectType: searchForm.inspectType || null,
-    inspectState: searchForm.inspectState || null,
+    checkType: searchForm.checkType === '' ? null : searchForm.checkType,
+    entryDateStart: searchForm.entryDateStart,
+    entryDateEnd: searchForm.entryDateEnd,
     current: page.current,
     size: page.size
   };
@@ -227,12 +270,18 @@
       loadStatus.value = 'nomore';
     } else {
       loadStatus.value = 'loadmore';
-      page.current++;
     }
   }).catch(() => {
-    loadStatus.value = 'loadmore';
+    loadStatus.value = 'error';
   });
 };
+
+const loadMore = () => {
+  if (loadStatus.value === 'nomore' || loadStatus.value === 'loading') return
+  loadStatus.value = 'loading'
+  page.current++
+  getList()
+}
 
 const handleQuery = () => {
   page.current = 1;
@@ -243,27 +292,55 @@
 };
 
 const selectType = (e) => {
-  searchForm.inspectType = e.value;
+  searchForm.checkType = e.value;
   handleQuery();
 };
 
-const selectStatus = (e) => {
-  searchForm.inspectState = e.value;
-  handleQuery();
-};
+const openDateRange = () => {
+  entryStartValue.value = searchForm.entryDateStart ? dayjs(searchForm.entryDateStart, 'YYYY-MM-DD').valueOf() : Date.now()
+  showEntryStartPicker.value = true
+}
+const confirmEntryStart = (e) => {
+  const ts = e?.value ?? entryStartValue.value
+  searchForm.entryDateStart = dayjs(ts).format('YYYY-MM-DD')
+  showEntryStartPicker.value = false
+  entryEndValue.value = searchForm.entryDateEnd ? dayjs(searchForm.entryDateEnd, 'YYYY-MM-DD').valueOf() : Date.now()
+  showEntryEndPicker.value = true
+}
+const confirmEntryEnd = (e) => {
+  const ts = e?.value ?? entryEndValue.value
+  searchForm.entryDateEnd = dayjs(ts).format('YYYY-MM-DD')
+  showEntryEndPicker.value = false
+  handleQuery()
+}
 
 const openDealDialog = (item) => {
   currentItem.value = item;
   dealForm.id = item.id;
-  dealForm.dealResult = '';
+  dealForm.defectivePhenomena = item.defectivePhenomena || ''
+  dealForm.dealResult = item.dealResult || '';
+  dealForm.dealName = item.dealName || ''
   dealForm.dealTime = dayjs().format('YYYY-MM-DD');
   dealDialogVisible.value = true;
 };
 
+const selectDealResult = (e) => {
+  dealForm.dealResult = e.value
+  showDealResultSelect.value = false
+}
+
 const submitDeal = () => {
-  if (!dealForm.dealResult) {
-    toast('璇疯緭鍏ュ鐞嗙粨鏋�');
+  if (!dealForm.defectivePhenomena) {
+    toast('璇疯緭鍏ヤ笉鍚堟牸鐜拌薄')
     return;
+  }
+  if (!dealForm.dealResult) {
+    toast('璇烽�夋嫨澶勭悊缁撴灉')
+    return
+  }
+  if (!dealForm.dealName) {
+    toast('璇疯緭鍏ュ鐞嗕汉')
+    return
   }
   submitLoading.value = true;
   qualityUnqualifiedDeal(dealForm).then(() => {
@@ -291,89 +368,115 @@
   showDatePicker.value = false;
 };
 
+const openForm = (type, row) => {
+  if (type !== 'add' && row?.inspectState == 1) {
+    toast('宸插鐞嗙殑鏁版嵁涓嶈兘鍐嶇紪杈�')
+    return
+  }
+  const id = row?.id
+  uni.navigateTo({
+    url: `/pages/qualityManagement/nonconformingManagement/form?type=${type}${id ? `&id=${id}` : ''}`
+  })
+}
+
 const goBack = () => {
   uni.navigateBack();
 };
 
-onMounted(() => {
-  handleQuery();
-});
+onShow(() => {
+  handleQuery()
+})
+
+onReachBottom(() => {
+  loadMore()
+})
 </script>
 
 <style lang="scss" scoped>
 .nonconforming-management-page {
-  padding-bottom: 20rpx;
-  background-color: #f5f7fa;
   min-height: 100vh;
+  background: #f5f5f5;
+  padding-bottom: 120rpx;
 }
 
 .search-section {
-  padding: 20rpx 30rpx;
-  background-color: #ffffff;
-  position: sticky;
-  top: 0;
-  z-index: 10;
+  background: #fff;
+  margin: 24rpx;
+  padding: 24rpx;
+  border-radius: 16rpx;
 }
+
+.search-row { display: flex; align-items: center; margin-bottom: 20rpx; }
+.search-input-wrap { flex: 1; margin-right: 20rpx; min-width: 0; }
+.btn-search {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  width: 180rpx;
+  min-height: 72rpx;
+  flex-shrink: 0;
+  padding: 20rpx 24rpx;
+  background: #2979ff;
+  color: #fff;
+  border-radius: 12rpx;
+  font-size: 28rpx;
+  box-sizing: border-box;
+  text-align: center;
+}
+.btn-search-inner { display: flex; flex-direction: row; align-items: center; justify-content: center; gap: 8rpx; }
 
 .filter-row {
   display: flex;
-  justify-content: space-around;
-  padding: 10rpx 0;
+  gap: 20rpx;
 }
 
 .filter-item {
-  display: flex;
-  align-items: center;
-  gap: 10rpx;
-  font-size: 28rpx;
-  color: #606266;
-}
-
-.list-container {
-  padding: 20rpx;
-}
-
-.list-item {
-  background-color: #ffffff;
-  border-radius: 16rpx;
-  padding: 30rpx;
-  margin-bottom: 20rpx;
-  box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.05);
-}
-
-.item-header {
-  display: flex;
-  justify-content: space-between;
-  align-items: center;
-  margin-bottom: 20rpx;
-}
-
-.product-name {
-  font-size: 30rpx;
-  font-weight: bold;
-  color: #303133;
-}
-
-.item-content {
-  margin-bottom: 20rpx;
-}
-
-.item-row {
-  display: flex;
-  margin-bottom: 10rpx;
-}
-
-.item-label {
-  color: #909399;
-  width: 180rpx;
-  font-size: 28rpx;
-}
-
-.item-value {
   flex: 1;
-  color: #303133;
-  font-size: 28rpx;
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  padding: 18rpx 20rpx;
+  background: #f5f5f5;
+  border-radius: 12rpx;
+  font-size: 26rpx;
+  color: #666;
 }
+
+.list-section { padding: 0 24rpx; }
+.card-item {
+  background: #fff;
+  border-radius: 16rpx;
+  padding: 16rpx 20rpx;
+  margin-bottom: 20rpx;
+  box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.06);
+}
+.card-header { padding: 2rpx 0 6rpx; }
+.header-main { display: flex; justify-content: space-between; align-items: center; gap: 16rpx; }
+.product-name { font-size: 30rpx; font-weight: 500; color: #333; flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
+.header-sub { display: flex; justify-content: space-between; gap: 16rpx; margin-top: 6rpx; }
+.sub-title { font-size: 24rpx; color: #999; flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
+.sub-right { font-size: 24rpx; color: #999; flex-shrink: 0; }
+.card-body .row { display: flex; justify-content: space-between; padding: 6rpx 0; font-size: 26rpx; }
+.card-body .l { color: #666; width: 180rpx; flex-shrink: 0; }
+.card-body .r { color: #333; flex: 1; text-align: right; word-break: break-all; }
+.card-actions {
+  display: flex;
+  gap: 16rpx;
+  justify-content: flex-end;
+  align-items: center;
+  margin-top: 12rpx;
+  padding-top: 14rpx;
+  border-top: 1rpx solid #eee;
+}
+.btn-link {
+  font-size: 28rpx;
+  padding: 10rpx 22rpx;
+  border-radius: 999rpx;
+  border: 1rpx solid transparent;
+}
+.btn-link-primary { color: #2979ff; border-color: rgba(41, 121, 255, 0.4); background: rgba(41, 121, 255, 0.08); }
+.btn-link-plain { color: #606266; border-color: rgba(96, 98, 102, 0.35); background: rgba(96, 98, 102, 0.06); }
+.btn-link-warn { color: #f56c6c; border-color: rgba(245, 108, 108, 0.55); background: rgba(245, 108, 108, 0.08); }
 
 .text-error {
   color: #f56c6c;
@@ -383,17 +486,8 @@
   color: #67c23a;
 }
 
-.item-actions {
-  display: flex;
-  justify-content: flex-end;
-  gap: 20rpx;
-  border-top: 1rpx solid #ebeef5;
-  padding-top: 20rpx;
-}
-
-.no-data {
-  padding-top: 200rpx;
-}
+.no-data { text-align: center; padding: 60rpx 0; color: #999; font-size: 28rpx; }
+.load-more-wrap { padding: 24rpx 24rpx 8rpx; }
 
 .dialog-content {
   width: 650rpx;
@@ -431,4 +525,23 @@
 .dialog-footer {
   margin-top: 40rpx;
 }
+
+.selector-trigger { display: flex; align-items: center; justify-content: space-between; padding: 20rpx 24rpx; background: #f5f5f5; border-radius: 12rpx; }
+.selector-text { font-size: 28rpx; color: #333; }
+.selector-text.placeholder { color: #999; }
+
+.fab-button {
+  position: fixed;
+  right: 36rpx;
+  bottom: 72rpx;
+  width: 104rpx;
+  height: 104rpx;
+  border-radius: 52rpx;
+  background: #2979ff;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  box-shadow: 0 10rpx 26rpx rgba(41, 121, 255, 0.35);
+  z-index: 20;
+}
 </style>

--
Gitblit v1.9.3