Prechádzať zdrojové kódy

Merge branch 'cpq-dev' of wangfan/adweb3-web into master

chenpeiqing 1 mesiac pred
rodič
commit
ade26d3444

+ 14 - 0
src/assets/enquiry/enquiryRules/checked.svg

@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="200px" height="200px" viewBox="0 0 200 200" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <!-- Generator: Sketch 63 (92445) - https://sketch.com -->
+    <title>选中</title>
+    <desc>Created with Sketch.</desc>
+    <g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g id="选中">
+            <circle id="椭圆形" fill="#544BEB" cx="100" cy="100" r="100"></circle>
+            <g id="选择" transform="translate(40.000000, 50.000000)" fill="#FFFFFF" fill-rule="nonzero">
+                <path d="M127.777857,1.54841111 C125.614837,-0.480107293 122.203409,-0.383208092 120.17489,1.78530783 L48.4163055,78.1869522 L9.21727745,39.5635342 C7.09735565,37.4757192 3.69113403,37.4974131 1.6033191,39.6173349 C-0.484495835,41.7320501 -0.457595393,45.1434783 1.66261562,47.2257974 L44.7896742,89.712454 C44.8058723,89.7286521 44.8272769,89.7338587 44.8434749,89.7500567 C44.859673,89.7662547 44.8648796,89.7876594 44.8810776,89.8038574 C45.22008,90.1266617 45.6290811,90.3097577 46.0218841,90.5249606 C46.2156824,90.6380578 46.3822911,90.8046664 46.5867916,90.8853675 C47.2216979,91.1329665 47.8942068,91.2619726 48.5615092,91.2619726 C49.2664144,91.2619726 49.9713193,91.121975 50.6276303,90.8422691 C50.848329,90.7508657 51.0204334,90.5625633 51.224934,90.4439702 C51.6284393,90.2070735 52.0481428,90.0080687 52.392641,89.6583641 C52.408839,89.642166 52.4140456,89.6152656 52.4302436,89.5990676 C52.4409459,89.5828695 52.4626397,89.5776629 52.4785485,89.5614649 L128.008679,9.15079941 C130.053685,6.99356432 129.940877,3.58763192 127.777857,1.54841111 Z" id="路径"></path>
+            </g>
+        </g>
+    </g>
+</svg>

+ 30 - 0
src/assets/enquiry/enquiryRules/quyuguanli.svg

@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 24.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 viewBox="0 0 200 200" style="enable-background:new 0 0 200 200;" xml:space="preserve">
+<style type="text/css">
+	.st0{fill:#999999;}
+</style>
+<title>区域管理备份</title>
+<desc>Created with Sketch.</desc>
+<g id="页面-1">
+	<g id="区域管理备份">
+		<path id="形状" class="st0" d="M45.2,106.1c2.3,2.1,5.8,2.1,8,0c27.5-25,40.8-45,40.8-61.2C94,20.1,73.9,0,49.2,0
+			S4.3,20.1,4.3,44.8C4.3,61.1,17.7,81.1,45.2,106.1z M49.2,6C70,6,86.9,22.9,86.9,43.7c0,9.4-6.7,26.6-37.7,55.7
+			c-31-29.2-37.7-46.3-37.7-55.7C11.5,22.9,28.4,6,49.2,6z M49.6,26.6C40.4,26.6,33,34,33,43.2c0,9.2,7.4,16.6,16.6,16.6
+			s16.6-7.4,16.6-16.6C66.2,34,58.8,26.6,49.6,26.6z M49.6,52.9c-5.4,0-9.7-4.4-9.7-9.7s4.4-9.7,9.7-9.7s9.7,4.4,9.7,9.7
+			C59.3,48.6,55,52.9,49.6,52.9z M173.5,46.7c-3.6-4.2-7.6-7.9-11.8-11.4c-0.4-0.5-0.8-0.8-1.3-1.1C144.1,21.2,123.8,14,102.7,14
+			c-2.3,0-4.2,1.9-4.2,4.2s1.9,4.2,4.2,4.2c15.6,0,30.6,4.3,43.6,12.1c-5.3,1.1-11.4,3.3-16.5,8c-7.1,6.5-10.5,15.9-10.3,28.1
+			c0.5,24.5,17.7,38.2,27.9,44.1l0.8,0.5c2.3,1.5,3.7,3.9,3.8,6.7c0.1,2.8-1,5.4-3.2,7.1c-6.1,4.7-16.1,14.7-14.1,28.7
+			c1.6,10.8,9.2,17.6,13.3,20.5c-12.5,8-27.2,12.8-43,13.2c4.4-6.2,9.6-15.7,8.8-25.7c-0.6-7.7-4.5-14.3-11.6-19.5
+			c-16.7-12.3-34.9-7.6-44.9-3.4c-1.4,0.5-2.6,0.5-3.7,0c-2-1-3.8-3.6-4.8-7.1c-3.9-12.8-14.8-19.4-30-18.3
+			c-0.4-3.4-0.7-6.8-0.7-10.3c0-2.3-1.9-4.2-4.2-4.2s-4.2,1.9-4.2,4.2c0,48.9,38,89,86,92.6c0.2,0,0.4,0.1,0.6,0.1
+			c0.1,0,0.2-0.1,0.4-0.1c2,0.1,4,0.3,6.1,0.3c51.3,0,93-41.7,93-93C195.7,84.9,187.8,63.5,173.5,46.7L173.5,46.7z M20.3,125.6
+			c8-0.4,17.2,1.7,20.5,12.4c1.8,5.9,5.1,10.2,9.2,12.3c3.2,1.6,6.8,1.7,10.4,0.4l1-0.4c9.4-4,23.2-6.7,35.9,2.7
+			c5.1,3.8,7.8,8.1,8.2,13.3c0.8,10.4-7.7,21.1-10.9,24.8C58,187.6,28.3,160.7,20.3,125.6z M155.4,172.9c-0.2-0.2-0.4-0.4-0.6-0.5
+			c-0.1,0-10.1-5.6-11.7-16c-1.4-9.7,6.2-17.1,10.8-20.7c4.4-3.3,6.8-8.6,6.5-14.2c-0.2-5.5-3.2-10.5-7.8-13.5l-1-0.6
+			c-8.7-5-23.3-16.5-23.7-36.9c-0.2-9.6,2.3-16.9,7.5-21.6c7.1-6.6,17.5-6.9,21.1-6.8c3.7,3.1,7.3,6.4,10.4,10.2
+			c13,15.2,20.1,34.7,20.1,54.8C187.2,133.6,174.7,157.4,155.4,172.9L155.4,172.9z"/>
+	</g>
+</g>
+</svg>

+ 16 - 0
src/assets/enquiry/enquiryRules/uncheck.svg

@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 24.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 viewBox="0 0 200 200" style="enable-background:new 0 0 200 200;" xml:space="preserve">
+<style type="text/css">
+	.st0{fill:#999999;}
+</style>
+<title>椭圆形备份</title>
+<desc>Created with Sketch.</desc>
+<g id="页面-1">
+	<g id="椭圆形备份">
+		<path class="st0" d="M100,200C44.9,200,0,155.1,0,100C0,44.9,44.9,0,100,0c55.1,0,100,44.9,100,100C200,155.1,155.1,200,100,200z
+			 M100,10c-49.6,0-90,40.4-90,90s40.4,90,90,90s90-40.4,90-90S149.6,10,100,10z"/>
+	</g>
+</g>
+</svg>

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 7 - 0
src/assets/enquiry/enquiryRules/wanquankaifang.svg


+ 91 - 98
src/views/adweb/data/components/CompanyList.vue

@@ -1,118 +1,111 @@
 <template>
-    <div class="company-list">
-        <div v-for="company in companies" :key="company.name" class="company-card">
-            <div class="company-header">
-                <h3 class="company-name">{{ company.name }}</h3>
-                <a-button type="primary" size="small" @click="handleCompareClick(company)">
-                    对比
-                </a-button>
-            </div>
-            
-            <div class="company-stats">
-                <span>共 {{ company.totalRecords }} 条统记录</span>
-                <span>其中 {{ company.matchedRecords }} 条相匹配</span>
-            </div>
-            
-            <div class="company-contact">
-                <div class="contact-item">
-                    <span class="label">联系方式:</span>
-                    <div class="contact-actions">
-                        <a-button 
-                            v-for="action in ['google', 'bing', 'AI邮箱']" 
-                            :key="action"
-                            size="small"
-                        >
-                            {{ action }}
-                        </a-button>
-                    </div>
-                </div>
-                <div class="contact-item">
-                    <span class="label">联系地址:</span>
-                    <span>{{ company.address }}</span>
-                </div>
-                <div class="contact-item" v-if="company.phone">
-                    <span class="label">电话:</span>
-                    <span>{{ company.phone }}</span>
-                </div>
-                <div class="contact-item" v-if="company.email">
-                    <span class="label">邮箱:</span>
-                    <span>{{ company.email }}</span>
-                </div>
-            </div>
+  <div class="company-list">
+    <div v-for="company in companies" :key="company.name" class="company-card">
+      <div class="company-header">
+        <h3 class="company-name">{{ company.name }}</h3>
+        <a-button type="primary" size="small" @click="handleCompareClick(company)"> 对比 </a-button>
+      </div>
+
+      <div class="company-stats">
+        <span>共 {{ company.totalRecords }} 条统记录</span>
+        <span>其中 {{ company.matchedRecords }} 条相匹配</span>
+      </div>
+
+      <div class="company-contact">
+        <div class="contact-item">
+          <span class="label">联系方式:</span>
+          <div class="contact-actions">
+            <a-button v-for="action in ['google', 'bing', 'AI邮箱']" :key="action" size="small">
+              {{ action }}
+            </a-button>
+          </div>
+        </div>
+        <div class="contact-item">
+          <span class="label">联系地址:</span>
+          <span>{{ company.address }}</span>
+        </div>
+        <div class="contact-item" v-if="company.phone">
+          <span class="label">电话:</span>
+          <span>{{ company.phone }}</span>
+        </div>
+        <div class="contact-item" v-if="company.email">
+          <span class="label">邮箱:</span>
+          <span>{{ company.email }}</span>
         </div>
+      </div>
     </div>
+  </div>
 </template>
 
 <script lang="ts" setup>
-import { defineProps, defineEmits } from 'vue';
+  import { defineProps, defineEmits } from 'vue';
 
-const props = defineProps({
+  const props = defineProps({
     companies: {
-        type: Array,
-        required: true,
-        default: () => []
-    }
-});
-
-const emit = defineEmits(['compare']);
+      type: Array,
+      required: true,
+      default: () => [],
+    },
+  });
 
-const handleCompareClick = (company) => {
+  const emit = defineEmits(['compare']);
+  const handleCompareClick = (company) => {
     emit('compare', company);
-};
+  };
 </script>
 
 <style lang="less" scoped>
-.company-list {
+  .company-list {
     padding: 16px;
-    
+
     .company-card {
-        background: #fff;
-        border: 1px solid #e8e8e8;
-        border-radius: 8px;
-        padding: 16px;
-        margin-bottom: 16px;
-        
-        .company-header {
-            display: flex;
-            justify-content: space-between;
-            align-items: center;
-            margin-bottom: 12px;
-            
-            .company-name {
-                margin: 0;
-                font-size: 16px;
-                font-weight: 500;
-                color: #1890ff;
-            }
+      background: #fff;
+      border: 1px solid #e8e8e8;
+      border-radius: 8px;
+      padding: 16px;
+      margin-bottom: 16px;
+
+      .company-header {
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        margin-bottom: 12px;
+
+        .company-name {
+          margin: 0;
+          font-size: 16px;
+          font-weight: 500;
+          color: #1890ff;
         }
-        
-        .company-stats {
-            margin-bottom: 12px;
-            color: #666;
-            
-            span {
-                margin-right: 24px;
-            }
+      }
+
+      .company-stats {
+        margin-bottom: 12px;
+        color: #666;
+
+        span {
+          margin-right: 24px;
         }
-        
-        .company-contact {
-            .contact-item {
-                margin-bottom: 8px;
-                
-                .label {
-                    color: #666;
-                    margin-right: 8px;
-                }
-                
-                .contact-actions {
-                    display: inline-block;
-                    
-                    .ant-btn {
-                        margin-right: 8px;
-                    }
-                }
+      }
+
+      .company-contact {
+        .contact-item {
+          margin-bottom: 8px;
+
+          .label {
+            color: #666;
+            margin-right: 8px;
+          }
+
+          .contact-actions {
+            display: inline-block;
+
+            .ant-btn {
+              margin-right: 8px;
             }
+          }
         }
+      }
     }
-}
-</style> 
+  }
+</style>

+ 480 - 0
src/views/adweb/enquiry/AdwebEnquiryDistribution.vue

@@ -0,0 +1,480 @@
+<template>
+  <div class="content adweb-enquiry-distribution">
+    <a-spin :tip="loadingTip" :spinning="loadingStatus">
+      <div class="spin-content">
+        <a-row class="r0" :gutter="8" style="margin-bottom: 16px">
+          <a-col :xl="7" :xxl="6">
+            <div class="choose-site">
+              <span class="t1">站点:</span>
+              <select-site ref="selectSiteRef" @set-site-info="changeSite" select-width="100%" />
+            </div>
+          </a-col>
+        </a-row>
+        <a-row class="r1">
+          <a-col :xl="19" :xxl="20">
+            <a-row>
+              <a-col :span="24"><p class="title">分配规则:</p></a-col>
+              <a-col :span="8" :class="rulesOptions == 'MASTER' ? 'active' : ''">
+                <p class="t1">
+                  <img @click="changeRules('MASTER')" class="chooseImg" :src="rulesOptions == 'MASTER' ? checkImg : uncheckImg" alt="" />
+                  仅主账户可见
+                </p>
+                <p class="t2">(只有主账户可以查看询盘信息)</p>
+              </a-col>
+              <a-col :span="8" :class="rulesOptions == 'ALL' ? 'active' : ''">
+                <p class="t1">
+                  <img @click="changeRules('ALL')" class="chooseImg" :src="rulesOptions == 'ALL' ? checkImg : uncheckImg" alt="" />
+                  完全开放
+                </p>
+                <p class="t2">(客户主账号和员工账号均可在后台查看该站点所有询盘)</p>
+              </a-col>
+              <a-col :span="8" :class="rulesOptions == 'REGION' ? 'active' : ''">
+                <p class="t1">
+                  <img @click="changeRules('REGION')" class="chooseImg" :src="rulesOptions == 'REGION' ? checkImg : uncheckImg" alt="" />
+                  按买家地域分配
+                </p>
+                <p class="t2">(系统根据买家的国家,将询盘自动分配给对应的账号)</p>
+              </a-col>
+            </a-row>
+          </a-col>
+          <a-col
+            :xl="5"
+            :xxl="4"
+            v-if="!(userRole.indexOf('admin') > -1 || userRole.indexOf('adweb_site_manager') > -1 || userRole.indexOf('adweb_seo_manager') > -1)"
+          >
+            <router-link :to="{ path: '/enterprise/enterpriseUser' }">
+              <div class="add-account">
+                <a-icon type="user" />
+                <p>新增子账户</p>
+              </div>
+            </router-link>
+          </a-col>
+        </a-row>
+        <a-row class="r2" v-if="rulesOptions == 'REGION'">
+          <a-col :span="24">
+            <p class="tips">说明:系统根据买家的国家,将询盘自动分配给对应的账号,不能确定买卖国家或相关国家没有被分配的,将统一分配给主账号。</p>
+            <a-button type="primary" style="margin-bottom: 10px" @click="showDistributionArea">待分配区域</a-button>
+          </a-col>
+
+          <a-col :span="24">
+            <a-table
+              ref="table"
+              size="middle"
+              :scroll="{ x: true }"
+              rowKey="id"
+              :columns="columns"
+              :dataSource="dataSource"
+              :pagination="false"
+              :loading="loading"
+              class="j-table-force-nowrap"
+            >
+              <template #bodyCell="{ column, record }">
+                <template v-if="column.dataIndex === 'action'">
+                  <a-button v-if="record.id !== '-1'" type="primary" @click="getUsersTree(record.id)">负责区域</a-button>
+                  <span v-else>--</span>
+                </template>
+              </template>
+            </a-table>
+          </a-col>
+        </a-row>
+        <a-row class="r1">
+          <a-col :xl="19" :xxl="20">
+            <a-row>
+              <a-col :span="24"><p class="title">邮件发送规则:</p></a-col>
+              <a-col :span="8" :class="sendEmailOptions == 'MASTER' ? 'active' : ''">
+                <p class="t1">
+                  <img @click="changeSendEmailRules('MASTER')" class="chooseImg" :src="sendEmailOptions == 'MASTER' ? checkImg : uncheckImg" />
+                  仅主账户
+                </p>
+                <p class="t2">(只有主账户邮箱可以收到询盘邮件)</p>
+              </a-col>
+              <a-col :span="8" :class="sendEmailOptions == 'ALL' ? 'active' : ''">
+                <p class="t1">
+                  <img @click="changeSendEmailRules('ALL')" class="chooseImg" :src="sendEmailOptions == 'ALL' ? checkImg : uncheckImg" />
+                  所有人
+                </p>
+                <p class="t2">(客户主账号和员工账号邮箱均可收到询盘邮件)</p>
+              </a-col>
+            </a-row>
+          </a-col>
+        </a-row>
+      </div>
+    </a-spin>
+    <distribution-area @ok="modalFormOk" ref="distributionAreaRef" />
+  </div>
+</template>
+
+<script lang="ts" setup>
+  import distributionArea from './modules/distributionArea.vue';
+  import checkImg from '/@/assets/enquiry/enquiryRules/checked.svg';
+  import uncheckImg from '/@/assets/enquiry/enquiryRules/uncheck.svg';
+  import { getAction, postAction } from '/@/api/manage/manage';
+  import selectSite from '/@/components/Adweb/selectSite.vue';
+  import { nextTick, onMounted, reactive, ref } from 'vue';
+  import { useUserStore } from '@/store/modules/user';
+  import { useMessage } from '@/hooks/web/useMessage';
+  import { Modal } from 'ant-design-vue';
+  const { userInfo } = useUserStore();
+  const queryParam = reactive<any>({});
+  const rulesOptions = ref('');
+  const sendEmailOptions = ref('');
+  const columns = [
+    {
+      title: '用户名',
+      align: 'center',
+      dataIndex: 'realname',
+    },
+    {
+      title: '登录账号',
+      align: 'center',
+      dataIndex: 'username',
+    },
+    {
+      title: '已分配国家',
+      align: 'center',
+      dataIndex: 'countryNum',
+      customRender: function (text) {
+        return text >= 0 ? text : '-';
+      },
+    },
+    {
+      title: '询盘数',
+      align: 'center',
+      dataIndex: 'enquiryNum',
+    },
+    {
+      title: '操作',
+      align: 'center',
+      dataIndex: 'action',
+      scopedSlots: {
+        customRender: 'action',
+      },
+    },
+  ];
+  const url = {
+    list: '/usercountry/subAccounts',
+  };
+  let dataSource = reactive([]);
+  const loading = ref(false);
+  const distributionAreaRef = ref();
+
+  const siteId = ref();
+
+  const userRole = ref('');
+  const loadingTip = ref('');
+  const loadingStatus = ref(false);
+  const { createMessage } = useMessage();
+
+  const ipagination = {
+    current: 1,
+    pageSize: 30,
+    pageSizeOptions: ['15', '30', '50', '100'],
+    showTotal: (total, range) => {
+      return range[0] + '-' + range[1] + ' 共' + total + '条';
+    },
+    showQuickJumper: true,
+    showSizeChanger: true,
+    total: 0,
+  };
+
+  onMounted(() => {
+    userRole.value = userInfo?.roles.join(',');
+  });
+
+  function changeSite(selectedSiteInfo: any) {
+    loadingTip.value = '切换站点中...';
+    loadingStatus.value = true;
+    siteId.value = selectedSiteInfo.id;
+    dealSiteData();
+  }
+  //处理站点数据
+  function dealSiteData() {
+    let param = {
+      siteId: siteId.value,
+    };
+    getAction('/usercountry/getSiteBySiteId', param)
+      .then((res) => {
+        if (res.code == 200) {
+          let data = res.result;
+          //获取并处理站点分配规则
+          rulesOptions.value = data.enquiryDistributeType;
+          if (data.enquiryDistributeType === 'REGION') {
+            queryParam.siteId = siteId;
+            loadData(1);
+          }
+
+          //获取站点的发送邮箱规则
+          sendEmailOptions.value = data.enquirySendEmailType;
+        }
+      })
+      .finally(() => {
+        loadingStatus.value = false;
+        loadingTip.value = '';
+      });
+  }
+  //改变分配规则
+  function changeRules(e) {
+    if (
+      userRole.value.indexOf('admin') > -1 ||
+      userRole.value.indexOf('adweb_site_manager') > -1 ||
+      userRole.value.indexOf('adweb_seo_manager') > -1
+    ) {
+      createMessage.warning('管理员账号不可修改分配规则!');
+      return;
+    }
+
+    Modal.confirm({
+      title: '修改分配规则',
+      content: `您确定要修改吗?`,
+      centered: true,
+      onOk: () => {
+        loadingTip.value = '改变分配规则中,请稍等...';
+        loadingStatus.value = true;
+        postAction('/usercountry/updateDistributeType?distributeType=' + e + '&siteId=' + siteId.value, {}, 60000)
+          .then((res) => {
+            if (res.success) {
+              rulesOptions.value = e;
+              if (e === 'REGION') {
+                queryParam.siteId = siteId;
+                loadData(1);
+              }
+            } else {
+              if (res.code == 403) {
+                createMessage.warning(res.message);
+              } else {
+                createMessage.error('修改失败,请联系管理员');
+              }
+            }
+          })
+          .finally(() => {
+            loadingStatus.value = false;
+            loadingTip.value = '';
+          });
+      },
+    });
+  }
+
+  function showDistributionArea() {
+    nextTick(() => {
+      distributionAreaRef.value.init(siteId.value);
+    });
+  }
+
+  function getUsersTree(id) {
+    nextTick(() => {
+      console.log(id, siteId.value, 'id, siteId.value');
+
+      distributionAreaRef.value.getUsersTree(id, siteId.value);
+    });
+  }
+
+  //改变邮箱接收邮件规则
+  function changeSendEmailRules(e) {
+    if (
+      userRole.value.indexOf('admin') > -1 ||
+      userRole.value.indexOf('adweb_site_manager') > -1 ||
+      userRole.value.indexOf('adweb_seo_manager') > -1
+    ) {
+      createMessage.warning('管理员账号不可修改分配规则!');
+      return;
+    }
+
+    Modal.confirm({
+      title: '修改邮件发送规则',
+      content: `您确定要修改吗?`,
+      centered: true,
+      onOk: () => {
+        loadingTip.value = '改变邮件规则中,请稍等...';
+        loadingStatus.value = true;
+        postAction('/usercountry/updateSendEmailType?sendEmailType=' + e + '&siteId=' + siteId.value, {}, 120000)
+          .then((res) => {
+            if (res.success) {
+              sendEmailOptions.value = e;
+            } else {
+              if (res.code == 403) {
+                createMessage.warning(res.message);
+              } else {
+                createMessage.error('修改失败,请联系管理员');
+              }
+            }
+          })
+          .finally(() => {
+            loadingStatus.value = false;
+            loadingTip.value = '';
+          });
+      },
+    });
+  }
+
+  function modalFormOk() {
+    // 新增/修改 成功时,重载列表
+    loadData(0);
+  }
+
+  function loadData(arg) {
+    if (!url.list) {
+      createMessage.error('请设置url.list属性!');
+      return;
+    }
+    //加载数据 若传入参数1则加载第一页的内容
+    if (arg === 1) {
+      ipagination.current = 1;
+    }
+
+    loading.value = true;
+    getAction(url.list, queryParam).then((res) => {
+      if (res.success) {
+        dataSource = res.result.records || res.result;
+        if (res.result.total != 0) {
+          ipagination.total = res.result.total;
+        } else {
+          ipagination.total = 0;
+        }
+      }
+      if (res.code === 510) {
+        createMessage.warning(res.message);
+      }
+      loading.value = false;
+    });
+  }
+</script>
+
+<style lang="less" scoped>
+  :deep(.spin-content .ant-row) {
+    margin: 15px 0;
+  }
+
+  .r0 {
+    .choose-site {
+      display: flex;
+      align-items: center;
+
+      :deep(.ant-select-selection) {
+        background: transparent;
+        color: #fff;
+      }
+
+      :deep(.ant-select-selection__clear) {
+        background: transparent;
+      }
+
+      :deep(i),
+      :deep(.ant-calendar-range-picker-separator) {
+        color: #fff;
+      }
+    }
+
+    .t1 {
+      font-size: 18px;
+    }
+
+    .ant-calendar-picker {
+      margin-right: 20px;
+
+      :deep(.ant-input) {
+        background: transparent;
+        color: #e2e2e2;
+      }
+    }
+
+    :deep(.ant-btn) {
+      background: transparent;
+      color: #e2e2e2;
+      margin-right: 10px;
+
+      &.active {
+        background: #fff;
+        border-color: #fff;
+        color: @primary-color;
+      }
+    }
+  }
+
+  .r1 {
+    background: #fff;
+    border-radius: 10px;
+    padding: 20px;
+    color: #000;
+    margin-bottom: 10px;
+    .title {
+      font-size: 18px;
+      font-weight: 500;
+      color: #000;
+    }
+
+    .t1 {
+      color: #999;
+      margin-bottom: 5px;
+      font-size: 16px;
+
+      .chooseImg {
+        width: 20px;
+        cursor: pointer;
+        margin: -4px 10px 0 0;
+      }
+    }
+
+    .t2 {
+      color: #999;
+      margin-bottom: 0;
+      margin-left: 35px;
+    }
+
+    .active {
+      .t1 {
+        color: @primary-color;
+      }
+
+      .t2 {
+        color: #000;
+      }
+    }
+
+    .add-account {
+      background: rgb(242, 248, 255);
+      color: @primary-color;
+      text-align: center;
+      line-height: 1;
+      display: flex;
+      flex-direction: column;
+      justify-content: center;
+      align-items: center;
+      height: 95px;
+      border-radius: 10px;
+      cursor: pointer;
+      transition: all 0.3s;
+      &:hover {
+        background: @primary-color;
+        a {
+          color: #fff;
+        }
+        p {
+          color: #fff;
+        }
+        :deep(svg) {
+          color: #fff;
+        }
+      }
+
+      i {
+        padding-bottom: 10px;
+      }
+
+      p {
+        margin-bottom: 0;
+      }
+    }
+  }
+
+  .r2 {
+    background: #fff;
+    border-radius: 10px;
+    padding: 20px;
+    color: #000;
+    .tips {
+      margin-bottom: 10px;
+      color: #999;
+      font-size: 13px;
+    }
+  }
+</style>

+ 13 - 18
src/views/adweb/enquiry/components/AdwebEnquiryForm.vue

@@ -3,8 +3,7 @@
     <JFormContainer :disabled="disabled">
       <template #detail>
         <a-form ref="formRef" class="antd-modal-form" :labelCol="labelCol" :wrapperCol="wrapperCol">
-          <a-row>
-          </a-row>
+          <a-row />
         </a-form>
       </template>
     </JFormContainer>
@@ -12,18 +11,17 @@
 </template>
 
 <script lang="ts" setup>
-  import { ref, reactive, defineExpose, nextTick, defineProps, computed, onMounted } from 'vue';
-  import { defHttp } from '/@/utils/http/axios';
+  import { computed, defineExpose, defineProps, nextTick, reactive, ref } from 'vue';
   import { useMessage } from '/@/hooks/web/useMessage';
   import { getValueType } from '/@/utils';
   import { saveOrUpdate } from '../AdwebEnquiry.api';
   import { Form } from 'ant-design-vue';
   import JFormContainer from '/@/components/Form/src/container/JFormContainer.vue';
-  
+
   const props = defineProps({
     formDisabled: { type: Boolean, default: false },
-    formData: { type: Object, default: () => ({})},
-    formBpm: { type: Boolean, default: true }
+    formData: { type: Object, default: () => ({}) },
+    formBpm: { type: Boolean, default: true },
   });
   const formRef = ref();
   const useForm = Form.useForm;
@@ -36,23 +34,21 @@
   const wrapperCol = ref<any>({ xs: { span: 24 }, sm: { span: 16 } });
   const confirmLoading = ref<boolean>(false);
   //表单验证
-  const validatorRules = reactive({
-  });
+  const validatorRules = reactive({});
   const { resetFields, validate, validateInfos } = useForm(formData, validatorRules, { immediate: false });
 
   // 表单禁用
-  const disabled = computed(()=>{
-    if(props.formBpm === true){
-      if(props.formData.disabled === false){
+  const disabled = computed(() => {
+    if (props.formBpm === true) {
+      if (props.formData.disabled === false) {
         return false;
-      }else{
+      } else {
         return true;
       }
     }
     return props.formDisabled;
   });
 
-  
   /**
    * 新增
    */
@@ -68,10 +64,10 @@
       resetFields();
       const tmpData = {};
       Object.keys(formData).forEach((key) => {
-        if(record.hasOwnProperty(key)){
-          tmpData[key] = record[key]
+        if (record.hasOwnProperty(key)) {
+          tmpData[key] = record[key];
         }
-      })
+      });
       //赋值
       Object.assign(formData, tmpData);
     });
@@ -115,7 +111,6 @@
       });
   }
 
-
   defineExpose({
     add,
     edit,

+ 211 - 0
src/views/adweb/enquiry/modules/distributionArea.vue

@@ -0,0 +1,211 @@
+<template>
+  <a-drawer
+    :width="width"
+    placement="right"
+    :closable="true"
+    @close="handleCancel"
+    :keyboard="false"
+    :body-style="{ padding: '5px 24px 64px 24px' }"
+    :maskClosable="false"
+    v-model:open="visible"
+  >
+    <template #title>
+      <span v-if="onlyUser"> 负责区域 </span>
+      <span v-else
+        >{{ title }}
+        <span style="float: right; margin: -3px 20px 0 0"
+          >分配给:
+          <a-select v-model:value="user" style="width: 180px">
+            <a-select-option v-for="item in userList" :key="item.id" :value="item.id">
+              {{ item.username }}
+            </a-select-option>
+          </a-select>
+        </span>
+      </span>
+    </template>
+
+    <a-tree
+      checkable
+      v-if="treeData.length"
+      :tree-data="treeData"
+      v-model:checked-keys="checkdNode"
+      class="self-tree"
+      :defaultExpandAll="true"
+      :blockNode="false"
+      @check="onCheck"
+    />
+
+    <a-empty v-if="treeData.length == 0" />
+
+    <div class="drawer-footer">
+      <a-button @click="handleCancel" style="margin-bottom: 0">关闭</a-button>
+      <a-button :loading="loading" @click="handleOk" type="primary" style="margin-bottom: 0" v-if="treeData.length > 0">
+        {{ onlyUser ? '保存修改' : '确认分配' }}</a-button
+      >
+    </div>
+  </a-drawer>
+</template>
+
+<script lang="ts" setup>
+  import { getAction, postAction } from '/@/api/manage/manage';
+  import { useMessage } from '@/hooks/web/useMessage';
+  import { ref } from 'vue';
+
+  const { createMessage } = useMessage();
+
+  const title = ref('待分配区域');
+  const width = 700;
+  const onlyUser = ref(false);
+  const visible = ref(false);
+
+  let treeData = ref([]);
+  let checkdNode = ref([]);
+  let userList = ref([{ id: '', username: '' }]);
+  const user = ref('');
+  const id = ref('');
+  const loading = ref(false);
+  const siteId = ref('');
+
+  // 定义父组件的方法, 子组件调用父组件的方法
+  const emit = defineEmits(['ok']);
+
+  function reload() {
+    visible.value = true;
+    treeData.value = [];
+    checkdNode.value = [];
+    userList.value = [];
+    user.value = '';
+    loading.value = false;
+  }
+
+  function init(siteIdParam) {
+    siteId.value = siteIdParam;
+    reload();
+    onlyUser.value = false;
+    getAllTree();
+  }
+
+  function getAllTree() {
+    checkdNode.value = [];
+    id.value = '';
+    getAction('/usercountry/country/uncontribute?siteId=' + siteId.value, {}).then((res) => {
+      if (res.code == 200) {
+        treeData.value = res.result == null ? [] : res.result;
+
+        console.log(treeData, 'treeDatatreeData');
+      }
+    });
+
+    getAction('/usercountry/subAccounts/optionswithoutself', {}).then((res) => {
+      if (res.code == 200) {
+        userList.value = res.result;
+        user.value = res.result.length > 0 ? res.result[0].id : '';
+      }
+    });
+  }
+
+  //子账户直接进入获取到所有的已分配国家
+  function getUsersTree(idParam, siteIdParam) {
+    siteId.value = siteIdParam;
+    reload();
+    onlyUser.value = true;
+    id.value = idParam;
+    checkdNode.value = [];
+    getAction('/usercountry/country/charge?id=' + id.value + '&siteId=' + siteId.value, {}).then((res) => {
+      if (res.code == 200) {
+        treeData.value = res.result == null ? [] : res.result;
+        if (treeData.value.length > 0) {
+          for (let i in res.result) {
+            checkdNode.value.push(res.result[i].key);
+            for (let j in res.result[i].children) {
+              checkdNode.value.push(res.result[i].children[j].key);
+            }
+          }
+        }
+      }
+    });
+  }
+
+  function onCheck() {
+    console.log('onCheck', checkdNode);
+  }
+
+  function handleCancel() {
+    visible.value = false;
+  }
+
+  function handleOk() {
+    console.log(user.value, ' user.value', id.value, ' id.value');
+
+    if (user.value == '' && id.value == '') {
+      createMessage.warn('请先选择要分配的子用户');
+      return;
+    }
+
+    let d = {
+      uid: user.value == '' ? id.value : user.value,
+      countryIds: checkdNode.value.toString(),
+      siteId: siteId.value,
+    };
+    let url = onlyUser.value ? '/usercountry/contribute/delete' : '/usercountry/contribute/add';
+    loading.value = true;
+    postAction(url, d, 120000).then((res) => {
+      loading.value = false;
+      if (res.code == 200) {
+        createMessage.success('分配成功');
+        emit('ok');
+        if (onlyUser.value) {
+          getUsersTree(id, siteId);
+        } else {
+          getAllTree();
+        }
+      } else {
+        if (res.code == 403) {
+          createMessage.warning(res.message);
+        } else {
+          createMessage.error('分配失败');
+        }
+      }
+    });
+  }
+
+  // 暴漏子组件方法,引用该组件的父组件可直接调用该方法
+  defineExpose({ init, getUsersTree });
+</script>
+
+<style lang="less" scoped>
+  /** Button按钮间距 */
+  .ant-btn {
+    margin-left: 30px;
+    margin-bottom: 30px;
+    float: right;
+  }
+
+  .drawer-footer {
+    position: absolute;
+    bottom: 0px;
+    width: 100%;
+    border-top: 1px solid #e8e8e8;
+    padding: 10px 16px;
+    text-align: right;
+    left: 0;
+    background: #fff;
+    border-radius: 0 0 2px 2px;
+  }
+</style>
+
+<style lang="less">
+  .self-tree {
+    .ant-tree-child-tree {
+      width: 100%;
+      display: block;
+      overflow: hidden;
+      li {
+        width: 33.33%;
+        float: left;
+        display: inline-block;
+        padding: 5px 0;
+      }
+    }
+  }
+</style>

+ 60 - 71
src/views/adweb/enquiryPublicRules/publicBlackEmail/modules/EnquiryPublicBlackEmailModal.vue

@@ -1,93 +1,82 @@
 <template>
-  <a-drawer
-    :title="title"
-    :width="width"
-    placement="right"
-    :closable="false"
-    @close="close"
-    v-model:open="visible">
-    <enquiry-public-black-email-form ref="realForm" @ok="submitCallback" :disabled="disableSubmit"
-                                     normal></enquiry-public-black-email-form>
+  <a-drawer :title="title" :width="width" placement="right" :closable="false" @close="close" v-model:open="visible">
+    <enquiry-public-black-email-form ref="realForm" @ok="submitCallback" :disabled="disableSubmit" normal />
     <div class="drawer-footer">
-      <a-button @click="handleCancel" style="margin-bottom: 0;">关闭</a-button>
-      <a-button v-if="!disableSubmit" @click="handleOk" type="primary" style="margin-bottom: 0;">
-        提交
-      </a-button>
+      <a-button @click="handleCancel" style="margin-bottom: 0">关闭</a-button>
+      <a-button v-if="!disableSubmit" @click="handleOk" type="primary" style="margin-bottom: 0"> 提交 </a-button>
     </div>
   </a-drawer>
 </template>
 
 <script lang="ts" name="EnquiryPublicBlackEmailModal" setup>
-import EnquiryPublicBlackEmailForm from './EnquiryPublicBlackEmailForm.vue';
-import {nextTick, ref} from "vue";
+  import EnquiryPublicBlackEmailForm from './EnquiryPublicBlackEmailForm.vue';
+  import { nextTick, ref } from 'vue';
 
-const title = ref("操作");
-const width = ref(800);
-const visible = ref(false);
-const disableSubmit = ref(false);
-const realForm = ref();
+  const title = ref('操作');
+  const width = ref(800);
+  const visible = ref(false);
+  const disableSubmit = ref(false);
+  const realForm = ref();
 
+  const emit = defineEmits(['ok', 'close']);
 
-const emit = defineEmits(["ok", "close"])
+  async function add() {
+    visible.value = true;
+    await nextTick();
 
-async function add() {
-  visible.value = true
-  await nextTick();
+    realForm.value.add();
+  }
 
-  realForm.value.add();
-}
+  async function edit(record) {
+    visible.value = true;
+    await nextTick();
+    realForm.value.edit(record);
+  }
 
-async function edit(record) {
-  visible.value = true
-  await nextTick();
-  realForm.value.edit(record);
-}
+  async function close() {
+    emit('close');
+    await nextTick();
+    visible.value = false;
+  }
 
-async function close() {
-  emit('close');
-  await nextTick();
-  visible.value = false;
-}
+  function handleOk() {
+    realForm.value.submitForm();
+  }
 
-function handleOk() {
-  realForm.value.submitForm()
-}
+  function submitCallback() {
+    emit('ok');
+    visible.value = false;
+  }
 
-function submitCallback() {
-  emit('ok');
-  visible.value = false;
-}
-
-function handleCancel() {
-   close()
-}
-
-defineExpose({
-  title,
-  disableSubmit,
-  add,
-  edit
-});
+  function handleCancel() {
+    close();
+  }
 
+  defineExpose({
+    title,
+    disableSubmit,
+    add,
+    edit,
+  });
 </script>
 
 <style lang="less" scoped>
-/** Button按钮间距 */
-.ant-btn {
-  margin-left: 30px;
-  margin-bottom: 30px;
-  float: right;
-}
+  /** Button按钮间距 */
+  .ant-btn {
+    margin-left: 30px;
+    margin-bottom: 30px;
+    float: right;
+  }
 
-.drawer-footer {
-  position: absolute;
-  bottom: -8px;
-  width: 100%;
-  border-top: 1px solid #e8e8e8;
-  padding: 10px 16px;
-  text-align: right;
-  left: 0;
-  background: #fff;
-  border-radius: 0 0 2px 2px;
-}
+  .drawer-footer {
+    position: absolute;
+    bottom: -8px;
+    width: 100%;
+    border-top: 1px solid #e8e8e8;
+    padding: 10px 16px;
+    text-align: right;
+    left: 0;
+    background: #fff;
+    border-radius: 0 0 2px 2px;
+  }
 </style>

+ 48 - 0
src/views/adweb/enterprise/EnterpriseUserManage.api.ts

@@ -0,0 +1,48 @@
+import { defHttp } from '/@/utils/http/axios';
+import { useMessage } from '/@/hooks/web/useMessage';
+
+const { createConfirm } = useMessage();
+
+enum Api {
+  list = '/enterprise/user/list',
+  deleteOne = '/sys/user/delete',
+  deleteBatch = '/sys/user/deleteBatch',
+}
+
+/**
+ * 列表接口
+ * @param params
+ */
+export const list = (params) => defHttp.get({ url: Api.list, params });
+
+export const queryEnterpriseAll = (params) => defHttp.get({ url: '/enterprise/role/queryall', params });
+
+export const addEnterpriseUser = (params) => {
+  return defHttp.post({ url: '/enterprise/user/add', params });
+};
+/**
+ * 删除单个
+ */
+export const deleteOne = (params, handleSuccess) => {
+  return defHttp.delete({ url: Api.deleteOne, params }, { joinParamsToUrl: true }).then(() => {
+    handleSuccess();
+  });
+};
+/**
+ * 批量删除
+ * @param params
+ */
+export const batchDelete = (params, handleSuccess) => {
+  createConfirm({
+    iconType: 'warning',
+    title: '确认删除',
+    content: '是否删除选中数据',
+    okText: '确认',
+    cancelText: '取消',
+    onOk: () => {
+      return defHttp.delete({ url: Api.deleteBatch, data: params }, { joinParamsToUrl: true }).then(() => {
+        handleSuccess();
+      });
+    },
+  });
+};

+ 238 - 0
src/views/adweb/enterprise/EnterpriseUserManage.data.ts

@@ -0,0 +1,238 @@
+import { BasicColumn, FormSchema } from '@/components/Table';
+import { render } from '@/utils/common/renderUtils';
+import { rules } from '@/utils/helper/validator';
+
+export const columns: BasicColumn[] = [
+  {
+    title: '序号',
+    width: 60,
+    align: 'center',
+    dataIndex: 'seqNumber',
+  },
+  {
+    title: '用户名',
+    align: 'left',
+    dataIndex: 'realname',
+  },
+  {
+    title: '登录账号',
+    align: 'left',
+    dataIndex: 'username',
+  },
+  {
+    title: '头像',
+    align: 'left',
+    customRender: render.renderAvatar,
+    width: 80,
+  },
+  {
+    title: '类型',
+    align: 'left',
+    width: 80,
+    dataIndex: 'primaryAccount',
+    customRender: function ({ text }) {
+      return text ? '主账户' : '子账户';
+    },
+  },
+  {
+    title: '分配的询盘数',
+    align: 'left',
+    dataIndex: 'enquiryNum',
+  },
+
+  {
+    title: '手机号码',
+    align: 'left',
+    dataIndex: 'phone',
+    customRender: function ({ text }) {
+      return text === null ? '--' : text;
+    },
+  },
+  {
+    title: '邮箱',
+    align: 'left',
+    dataIndex: 'email',
+    customRender: function ({ text }) {
+      return text === null ? '--' : text;
+    },
+  },
+  {
+    title: '更新时间',
+    align: 'left',
+    dataIndex: 'updateTime',
+    customRender: function ({ text }) {
+      return text === null ? '--' : text;
+    },
+  },
+];
+
+export const subColumns: BasicColumn[] = [
+  {
+    title: '序号',
+    width: 60,
+    align: 'center',
+    dataIndex: 'seqNumber',
+  },
+  {
+    title: '用户名',
+    align: 'left',
+    dataIndex: 'realname',
+  },
+  {
+    title: '登录账号',
+    align: 'left',
+    dataIndex: 'username',
+  },
+  {
+    title: '头像',
+    align: 'left',
+    dataIndex: 'avatar',
+    width: 80,
+  },
+  {
+    title: '类型',
+    align: 'left',
+    width: 80,
+    dataIndex: 'primaryAccount',
+    customRender: function ({ text }) {
+      return text ? '主账户' : '子账户';
+    },
+  },
+  {
+    title: '性别',
+    align: 'left',
+    dataIndex: 'sex',
+    customRender: function ({ text }) {
+      if (text === null) {
+        return '-';
+      }
+      return text === 1 ? '男' : '女';
+    },
+  },
+  {
+    title: '手机号码',
+    align: 'left',
+    dataIndex: 'phone',
+    customRender: function ({ text }) {
+      return text === null ? '--' : text;
+    },
+  },
+  {
+    title: '邮箱',
+    align: 'left',
+    dataIndex: 'email',
+    customRender: function ({ text }) {
+      return text === null ? '--' : text;
+    },
+  },
+  {
+    title: '更新时间',
+    align: 'left',
+    dataIndex: 'updateTime',
+    customRender: function ({ text }) {
+      return text === null ? '--' : text;
+    },
+  },
+  {
+    title: '主账号询盘',
+    align: 'center',
+    dataIndex: 'isInquiry',
+    customRender: function ({ text }) {
+      return text === 1 ? '不接收' : '接收中';
+    },
+  },
+  {
+    title: '询盘接收',
+    dataIndex: 'action',
+    fixed: 'right',
+
+    align: 'left',
+  },
+];
+
+export const formSchema: FormSchema[] = [
+  {
+    label: '',
+    field: 'id',
+    component: 'Input',
+    show: false,
+  },
+  {
+    label: '用户账号',
+    field: 'username',
+    component: 'Input',
+    dynamicDisabled: ({ values }) => {
+      return !!values.id;
+    },
+    dynamicRules: ({ model, schema }) => rules.duplicateCheckRule('sys_user', 'username', model, schema, true),
+  },
+  {
+    label: '登录密码',
+    field: 'password',
+    component: 'StrengthMeter',
+    componentProps: {
+      autocomplete: 'new-password',
+    },
+    rules: [
+      {
+        required: true,
+        message: '请输入登录密码',
+      },
+      {
+        pattern: /^(?=.*[a-zA-Z])(?=.*\d)(?=.*[~!@#$%^&*()_+`\-={}:";'<>?,./]).{8,}$/,
+        message: '密码由8位数字、大小写字母和特殊符号组成!',
+      },
+    ],
+    ifShow: ({ values }) => {
+      return !values.id;
+    },
+  },
+  {
+    label: '确认密码',
+    field: 'confirmPassword',
+    component: 'InputPassword',
+    dynamicRules: ({ values }) => rules.confirmPassword(values, true),
+    ifShow: ({ values }) => {
+      return !values.id;
+    },
+  },
+  {
+    label: '公司名称',
+    field: 'realname',
+    required: true,
+    component: 'Input',
+  },
+  {
+    label: '手机号码',
+    field: 'phone',
+    component: 'Input',
+    required: true,
+    dynamicRules: ({ model, schema }) => {
+      return [
+        { ...rules.duplicateCheckRule('sys_user', 'phone', model, schema, true)[0], trigger: 'blur' },
+        { pattern: /^1[3456789]\d{9}$/, message: '手机号码格式有误', trigger: 'blur' },
+      ];
+    },
+  },
+  {
+    label: '邮箱',
+    field: 'email',
+    component: 'Input',
+    required: true,
+    dynamicRules: ({ model, schema }) => {
+      return [
+        { ...rules.duplicateCheckRule('sys_user', 'email', model, schema, true)[0], trigger: 'blur' },
+        { ...rules.rule('email', false)[0], trigger: 'blur' },
+      ];
+    },
+  },
+
+  {
+    label: '头像',
+    field: 'avatar',
+    component: 'JImageUpload',
+    componentProps: {
+      fileMax: 1,
+    },
+  },
+];

+ 302 - 0
src/views/adweb/enterprise/EnterpriseUserManageList.vue

@@ -0,0 +1,302 @@
+<template>
+  <a-card :bordered="false">
+    <!-- 查询区域 -->
+    <div class="table-page-search-wrapper">
+      <a-form layout="inline" @keyup.enter.native="searchQuery" style="display: block">
+        <a-row :gutter="24">
+          <a-col :md="6" :sm="12">
+            <a-form-item>
+              <a-input placeholder="请输入用户账号/用户名/手机号" v-model:value="queryParam.queryCondition" />
+            </a-form-item>
+          </a-col>
+          <a-col :md="18" :sm="12">
+            <span style="float: left; overflow: hidden" class="table-page-search-submitButtons">
+              <a-button type="primary" @click="searchQuery" preIcon="ant-design:search-outlined">查询</a-button>
+              <a-button ghost type="primary" @click="searchReset" preIcon="ant-design:reload-outlined" style="margin-left: 8px">重置</a-button>
+              <a-button ghost @click="handleAdd" type="primary" style="margin-left: 8px" preIcon="ant-design:plus-outlined">添加子用户</a-button>
+              <a-button ghost type="primary" @click="showRecycleBin" style="margin-left: 8px" preIcon="ant-design:hdd-outlined">回收站</a-button>
+              <router-link :to="{ path: '/inquery/rules' }" v-if="siteCode !== dictSiteCode">
+                <a-button ghost type="primary" preIcon="ant-design:logout-outlined" @click="showRecycleBin" style="margin-left: 8px"
+                  >配置询盘规则</a-button
+                >
+              </router-link>
+            </span>
+          </a-col>
+        </a-row>
+      </a-form>
+    </div>
+
+    <!-- table区域-begin -->
+    <div v-if="siteCode !== dictSiteCode">
+      <BasicTable @register="registerTable" :rowSelection="rowSelection">
+        <template #action="{ record }">
+          <div style="padding: 8px; display: flex; justify-content: space-evenly">
+            <a-tag color="purple" @click="handleEdit(record)" style="cursor: pointer"> 编辑 </a-tag>
+            <a-tag color="green" @click="handleChangePassword(record.username)" style="cursor: pointer"> 重置密码 </a-tag>
+            <a-popconfirm v-if="!record.primaryAccount" title="确定删除吗?" @confirm="() => handleFrozen(record.id, 2)">
+              <a-tag color="red" style="cursor: pointer"> 删除 </a-tag>
+            </a-popconfirm>
+          </div>
+        </template>
+      </BasicTable>
+    </div>
+    <!-- table区域-end -->
+
+    <!--    table-子账户轮询-begin-->
+    <div v-if="siteCode === dictSiteCode">
+      <h1>关闭配置或新增子账号会重置轮流分配</h1>
+      <a-table
+        ref="table"
+        size="middle"
+        rowKey="id"
+        :scroll="{ x: true }"
+        :columns="subColumns"
+        :dataSource="subAccountList"
+        :pagination="ipagination1"
+        :loading="loading"
+        @change="handleTableChange"
+      >
+        <template #avatarslot="text, record, index">
+          <div class="anty-img-wrap" style="margin-bottom: 5px">
+            <a-avatar shape="square" :src="getAvatarView(record.avatar)" icon="user" />
+          </div>
+        </template>
+
+        <template #action="text, record">
+          <span>
+            <div>
+              <a-switch
+                :checked="record.isInquiry === 2"
+                @change="(checked) => handleSwitchChange(record, checked)"
+                checked-children="开"
+                un-checked-children="关"
+                :disabled="record.primaryAccount"
+              />
+            </div>
+          </span>
+        </template>
+
+        <template #action1="text, record">
+          <span>
+            <div style="padding: 8px">
+              <a-tag color="purple" @click="handleEdit(record)" style="cursor: pointer"> 编辑 </a-tag>
+              <!--            <a-tag v-if="!record.primaryAccount" color="orange" @click="handlePerssion(record.id)" style="cursor:pointer;">-->
+              <!--              菜单配置-->
+              <!--            </a-tag>-->
+              <a-tag color="green" @click="handleChangePassword(record.username)" style="cursor: pointer"> 重置密码 </a-tag>
+              <a-popconfirm v-if="!record.primaryAccount" title="确定删除吗?" @confirm="() => handleFrozen(record.id, 2)">
+                <a-tag color="red" style="cursor: pointer"> 删除 </a-tag>
+              </a-popconfirm>
+            </div>
+          </span>
+        </template>
+        <template #countSlot="text, record, index">
+          <span style="margin-left: 20px">{{ text }} 个</span>
+        </template>
+      </a-table>
+    </div>
+    <!--    table-子账户轮询-begin-->
+
+    <!-- 编辑、新增用户 -->
+    <enterprise-user-modal ref="registerModal" @ok="modalFormOk" />
+
+    <!--修改密码-->
+    <PasswordModal @register="registerPasswordModal" @success="reload" />
+
+    <!-- 用户回收站 -->
+    <enterprise-user-recycle-bin-modal ref="recycleBin" @ok="modalFormOk" />
+  </a-card>
+</template>
+
+<script lang="ts" setup>
+  import '@/assets/less/common.less';
+  import EnterpriseUserModal from './modules/EnterpriseUserModal.vue';
+
+  import { getAction, getFileAccessHttpUrl, putAction } from '@/api/manage/manage';
+  import EnterpriseUserRecycleBinModal from './modules/EnterpriseUserRecycleBinModal.vue';
+  import PasswordModal from '/@/views/system/user/PasswordModal.vue';
+
+  import { onBeforeMount, reactive, ref } from 'vue';
+  import { BasicTable } from '@/components/Table';
+  import { useMessage } from '@/hooks/web/useMessage';
+  import { useListPage } from '@/hooks/system/useListPage';
+  import { deleteOne, list } from '@/views/adweb/enterprise/EnterpriseUserManage.api';
+  import { columns, subColumns } from '@/views/adweb/enterprise/EnterpriseUserManage.data';
+  import { useModal } from '@/components/Modal';
+
+  let subAccountList = reactive([]);
+  const registerModal = ref();
+  const recycleBin = ref();
+  const ipagination1 = reactive({
+    current: 1,
+    pageSize: 10,
+    pageSizeOptions: ['10', '20', '30'],
+    showTotal: (total, range) => {
+      return range[0] + '-' + range[1] + ' 共' + total + '条';
+    },
+  });
+  let queryParam = reactive<any>({});
+  const loading = ref(false);
+  const siteCode = ref();
+  const dictSiteCode = ref();
+
+  const { createMessage } = useMessage();
+  //注册table数据
+  const { prefixCls, tableContext } = useListPage({
+    tableProps: {
+      title: '账户管理',
+      api: list,
+      columns,
+      canResize: false,
+      useSearchForm: false,
+      actionColumn: {
+        width: 180,
+        fixed: 'right',
+      },
+      striped: true,
+      bordered: false,
+      immediate: true, // 不直接触发,通过reload事件触发接口
+      beforeFetch: (params) => {
+        return Object.assign(params, queryParam);
+      },
+    },
+  });
+  const [
+    registerTable,
+    { reload, clearSelectedRowKeys, updateTableDataRecord, findTableDataRecord, getDataSource },
+    { rowSelection, selectedRowKeys },
+  ] = tableContext;
+
+  const [registerPasswordModal, { openModal: openPasswordModal }] = useModal();
+
+  onBeforeMount(() => {
+    subList();
+    siteCode.value = localStorage.getItem('siteCode');
+    getTurnInquiryCode();
+  });
+
+  //获取需要轮流询盘的站点code
+  function getTurnInquiryCode() {
+    getAction('/adweb/adwebEnquiry/getTurnInquiryCode', {}).then((res) => {
+      if (res.code === 200) {
+        dictSiteCode.value = res.result[0].value;
+      }
+    });
+  }
+  function handleFrozen(id, status) {
+    loading.value = true;
+    putAction('/enterprise/user/frozen', { ids: id, status: status }).then((res) => {
+      if (res.success) {
+        createMessage.success(res.message);
+        if (siteCode.value === dictSiteCode.value) {
+          subList();
+        } else {
+          reload();
+        }
+      } else {
+        createMessage.warning(res.message);
+      }
+      loading.value = false;
+    });
+  }
+  function getAvatarView(avatar) {
+    return getFileAccessHttpUrl(avatar, 'https');
+  }
+  function showRecycleBin() {
+    recycleBin.value.show();
+  }
+  function searchQuery() {
+    if (siteCode.value === dictSiteCode.value) {
+      subList();
+    } else {
+      reload();
+    }
+    clearSelectedRowKeys();
+  }
+  function searchReset() {
+    queryParam = {};
+    if (siteCode.value === dictSiteCode.value) {
+      subList();
+    } else {
+      reload();
+    }
+  }
+
+  /**
+   * 打开修改密码弹窗
+   */
+  function handleChangePassword(username) {
+    openPasswordModal(true, { username });
+  }
+
+  function handlePerssion(userId) {
+    this.$refs.modalUserRole.show(userId);
+  }
+
+  function modalFormOk() {
+    // 新增/修改 成功时,重载列表
+    if (siteCode.value === dictSiteCode.value) {
+      subList();
+    } else {
+      reload();
+    }
+  }
+  //获取子账户
+  function subList() {
+    let params = queryParam;
+    params.siteCode = localStorage.getItem('siteCode');
+    getAction('/enterprise/user/sub/list', params).then((res) => {
+      if (res.success) {
+        subAccountList = res.result.records;
+        ipagination1.total = res.result.total;
+      }
+      if (siteCode.value === dictSiteCode.value) {
+        loading.value = false;
+      }
+    });
+  }
+  function handleSwitchChange(record, checked) {
+    // 处理开关切换操作
+    record.isInquiry = checked ? 2 : 1;
+    putAction('/enterprise/user/updateIsInquiry', record).then((res) => {
+      if (res.success) {
+        createMessage.success(res.message);
+        subList();
+      } else {
+        createMessage.warning(res.message);
+        subList();
+      }
+    });
+  }
+
+  /**
+   * 新增事件
+   */
+  function handleAdd() {
+    registerModal.value.disableSubmit = false;
+    registerModal.value.title = '新增';
+    registerModal.value.add();
+  }
+
+  /**
+   * 编辑事件
+   */
+  function handleEdit(record: Recordable) {
+    registerModal.value.disableSubmit = false;
+    registerModal.value.edit(record);
+  }
+
+  /**
+   * 删除事件
+   */
+  async function handleDelete(record) {
+    await deleteOne({ id: record.id }, handleSuccess);
+  }
+
+  /**
+   * 成功回调
+   */
+  function handleSuccess() {
+    (selectedRowKeys.value = []) && reload();
+  }
+</script>

+ 218 - 0
src/views/adweb/enterprise/modules/EnterpriseUserModal.vue

@@ -0,0 +1,218 @@
+<template>
+  <BasicDrawer
+    :title="title"
+    :maskClosable="true"
+    :confirmLoading="confirmLoading"
+    :width="drawerWidth"
+    placement="right"
+    :closable="true"
+    @close="handleCancel"
+    v-model:open="visible"
+    style="height: 100%; overflow: auto; padding-bottom: 53px"
+  >
+    <BasicForm @register="registerForm" />
+
+    <div class="drawer-bootom-button" v-show="!disableSubmit">
+      <a-button @click="handleCancel" style="margin-right: 0.8rem">取消</a-button>
+      <a-button @click="handleSubmit" type="primary" :loading="confirmLoading">提交</a-button>
+    </div>
+  </BasicDrawer>
+</template>
+
+<script lang="ts" setup>
+  import { getAction, postAction } from '@/api/manage/manage';
+  import { formSchema } from '../EnterpriseUserManage.data';
+  import { onBeforeMount, ref } from 'vue';
+  import { useUserStore } from '/@/store/modules/user';
+  import { useMessage } from '@/hooks/web/useMessage';
+  import { BasicForm, useForm } from '@/components/Form';
+  import { BasicDrawer } from '@/components/Drawer';
+  import { getTenantId } from '/@/utils/auth';
+
+  const userStore = useUserStore();
+
+  let drawerWidth = ref(700);
+
+  let checkedDepartNameString = ref('');
+
+  let userId = ref('');
+  const disableSubmit = ref(false);
+
+  let departIdShow = ref(false);
+
+  const title = ref('操作');
+  const visible = ref(false);
+
+  const selectedRole = ref([]);
+
+  const confirmLoading = ref(false);
+
+  const picUrl = ref('');
+  const identity = ref('1');
+
+  let siteCode = ref('');
+  let dictSiteCode = ref('');
+  const url = {
+    fileUpload: window._CONFIG['domianURL'] + '/sys/common/upload',
+    userId: '/sys/user/generateUserId', // 引入生成添加用户情况下的url
+    syncUserByUserName: '/act/process/extActProcess/doSyncUserByUserName', //同步用户到工作流
+    queryTenantList: '/sys/tenant/queryList',
+  };
+  const emit = defineEmits(['ok', 'close', 'success']);
+
+  //表单配置
+  const [registerForm, { setProps, resetFields, setFieldsValue, validate, updateSchema }] = useForm({
+    labelWidth: 90,
+    schemas: formSchema,
+    showActionButtonGroup: false,
+  });
+
+  const { createMessage } = useMessage();
+
+  onBeforeMount(() => {
+    siteCode.value = localStorage.getItem('siteCode') ?? '';
+    getTurnInquiryCode();
+  });
+
+  function refresh() {
+    checkedDepartNameString.value = '';
+    userId.value = '';
+    departIdShow.value = false;
+  }
+
+  function add() {
+    picUrl.value = '';
+    refresh();
+    edit({ activitiSync: '1' });
+  }
+
+  function edit(record) {
+    resetScreenSize(); // 调用此方法,根据屏幕宽度自适应调整抽屉的宽度
+
+    checkedDepartNameString.value = '';
+
+    if (record.hasOwnProperty('id')) {
+      setFieldsValue({
+        ...record,
+      });
+    }
+    userId.value = record.id;
+
+    visible.value = true;
+  }
+
+  function close() {
+    emit('close');
+    visible.value = false;
+    disableSubmit.value = false;
+    selectedRole.value = [];
+    checkedDepartNameString.value = '';
+    departIdShow.value = false;
+    identity.value = '1';
+  }
+
+  async function handleSubmit() {
+    try {
+      let values = await validate();
+      confirmLoading.value = true;
+      values.userIdentity === 1 && (values.departIds = '');
+
+      let obj;
+      values.masterId = userStore.getUserInfo.id;
+      values.masterName = userStore.getUserInfo.username;
+
+      if (!values.id) {
+        values.siteCode = siteCode.value;
+        values.relTenantIds = getTenantId();
+        obj = postAction('/enterprise/user/add', values, 120000);
+      } else {
+        values.masterEmail = userStore.getUserInfo.email;
+        values.siteCode = siteCode;
+        obj = postAction('/enterprise/user/edit', values, 120000);
+      }
+      //提交表单
+      obj
+        .then((res) => {
+          if (res.code === 200) {
+            createMessage.success(res.message);
+            confirmLoading.value = false;
+            close();
+            emit('ok');
+          } else {
+            confirmLoading.value = false;
+            createMessage.warning(res.message);
+          }
+        })
+        .finally(() => {
+          //关闭弹窗
+          close();
+        });
+    } finally {
+      confirmLoading.value = false;
+    }
+  }
+
+  function handleCancel() {
+    close();
+  }
+
+  // 根据屏幕变化,设置抽屉尺寸
+  function resetScreenSize() {
+    let screenWidth = document.body.clientWidth;
+    if (screenWidth < 500) {
+      drawerWidth.value = screenWidth;
+    } else {
+      drawerWidth.value = 700;
+    }
+  }
+
+  //获取需要轮流询盘的站点code
+  function getTurnInquiryCode() {
+    getAction('/adweb/adwebEnquiry/getTurnInquiryCode', {}).then((res) => {
+      if (res.code === 200) {
+        dictSiteCode.value = res.result[0].value;
+      }
+    });
+  }
+
+  defineExpose({
+    add,
+    edit,
+    disableSubmit,
+    title,
+  });
+</script>
+
+<style scoped>
+  .avatar-uploader > .ant-upload {
+    width: 104px;
+    height: 104px;
+  }
+
+  .ant-upload-select-picture-card i {
+    font-size: 49px;
+    color: #999;
+  }
+
+  .ant-upload-select-picture-card .ant-upload-text {
+    margin-top: 8px;
+    color: #666;
+  }
+
+  .ant-table-tbody .ant-table-row td {
+    padding-top: 10px;
+    padding-bottom: 10px;
+  }
+
+  .drawer-bootom-button {
+    position: absolute;
+    bottom: -8px;
+    width: 100%;
+    border-top: 1px solid #e8e8e8;
+    padding: 10px 16px;
+    text-align: right;
+    left: 0;
+    background: #fff;
+    border-radius: 0 0 2px 2px;
+  }
+</style>

+ 162 - 0
src/views/adweb/enterprise/modules/EnterpriseUserRecycleBinModal.vue

@@ -0,0 +1,162 @@
+<template>
+  <a-drawer :title="title" :mask-closable="true" :width="1000" placement="right" :closable="true" @close="handleCancel" v-model:open="visible">
+    <a-table
+      ref="table"
+      size="middle"
+      rowKey="id"
+      :scroll="{ x: true }"
+      :columns="columns"
+      :dataSource="dataSource"
+      :pagination="ipagination"
+      :loading="loading"
+    >
+      <template #avatarslot="text, record, index">
+        <div class="anty-img-wrap" style="margin-bottom: 5px">
+          <a-avatar shape="square" :src="getAvatarView(record.avatar)" icon="user" />
+        </div>
+      </template>
+      <template #action="text, record">
+        <span>
+          <div style="padding: 8px">
+            <a-tag color="purple" @click="handleFrozen(record.id, 1)" style="cursor: pointer">恢复</a-tag>
+            <a-popconfirm title="确定删除吗(同时删除wp中的账户,账户下的产品会转移至主账户)?" @confirm="() => handleDelete(record.id)">
+              <a-tag color="red" style="cursor: pointer">删除</a-tag>
+            </a-popconfirm>
+          </div>
+        </span>
+      </template>
+      <template #countSlot="text, record, index">
+        <span style="margin-left: 20px">{{ text }} 个</span>
+      </template>
+    </a-table>
+  </a-drawer>
+</template>
+
+<script>
+  import { putAction, getFileAccessHttpUrl, deleteAction } from '@/api/manage/manage';
+
+  export default {
+    name: 'EnterpriseUserRecycleBinModal',
+
+    data() {
+      return {
+        title: '用户回收站',
+        loading: false,
+        visible: false,
+        selectedRowKeys: [],
+        columns: [
+          {
+            title: '序号',
+            dataIndex: '',
+            key: 'rowIndex',
+            width: 60,
+            align: 'center',
+            customRender: function (t, r, index) {
+              return parseInt(index) + 1;
+            },
+          },
+          {
+            title: '用户名',
+            align: 'left',
+            dataIndex: 'realname',
+          },
+          {
+            title: '登录账号',
+            align: 'left',
+            dataIndex: 'username',
+          },
+          {
+            title: '头像',
+            align: 'left',
+            dataIndex: 'avatar',
+            width: 80,
+            scopedSlots: { customRender: 'avatarslot' },
+          },
+          {
+            title: '类型',
+            align: 'left',
+            width: 80,
+            dataIndex: 'primaryAccount',
+            customRender: function (text) {
+              return text ? '主账户' : '子账户';
+            },
+          },
+          // {
+          //   title: '分配的询盘数',
+          //   align: "left",
+          //   dataIndex: 'enquiryNum',
+          //   scopedSlots: {customRender: "countSlot"}
+          // },
+          // {
+          //   title: '负责的产品数',
+          //   align: "left",
+          //   dataIndex: 'productNum',
+          //   scopedSlots: {customRender: "countSlot"}
+          // },
+          {
+            title: '手机号码',
+            align: 'left',
+            dataIndex: 'phone',
+            customRender: function (text) {
+              return text === null ? '--' : text;
+            },
+          },
+          {
+            title: '邮箱',
+            align: 'left',
+            dataIndex: 'email',
+            customRender: function (text) {
+              return text === null ? '--' : text;
+            },
+          },
+          {
+            title: '更新时间',
+            align: 'left',
+            dataIndex: 'updateTime',
+            customRender: function (text) {
+              return text === null ? '--' : text;
+            },
+          },
+          {
+            title: '操作',
+            dataIndex: 'action',
+            fixed: 'right',
+            scopedSlots: { customRender: 'action' },
+            align: 'center',
+          },
+        ],
+        url: {
+          getAvatar: (path) => getFileAccessHttpUrl(`${path}`),
+          list: '/enterprise/user/recycleBin',
+          delete: '/sys/user/delete',
+        },
+      };
+    },
+    methods: {
+      show() {
+        this.visible = true;
+        this.loadData(1);
+      },
+      handleCancel() {
+        this.visible = false;
+      },
+      handleFrozen: function (id, status) {
+        let that = this;
+        putAction('/enterprise/user/frozen', { ids: id, status: status }).then((res) => {
+          if (res.success) {
+            that.$message.success(res.message);
+            that.loadData();
+            that.$emit('ok');
+          } else {
+            that.$message.warning(res.message);
+          }
+        });
+      },
+      getAvatarView: function (avatar) {
+        return getFileAccessHttpUrl(avatar);
+      },
+    },
+  };
+</script>
+
+<style lang="less" scoped></style>

+ 59 - 68
src/views/adweb/keywords/SeoKeywords.data.ts

@@ -1,28 +1,23 @@
-import { BasicColumn } from "/@/components/Table";
-import { FormSchema } from "/@/components/Table";
-import { rules } from "/@/utils/helper/validator";
-import { render } from "/@/utils/common/renderUtils";
-import { getWeekMonthQuarterYear } from "/@/utils";
-import { defHttp } from "@/utils/http/axios";
+import { BasicColumn, FormSchema } from '/@/components/Table';
 //列表数据
 export const columns: BasicColumn[] = [
   {
-    title: "关键词",
-    align: "center",
-    dataIndex: "keywords",
+    title: '关键词',
+    align: 'center',
+    dataIndex: 'keywords',
     sorter: true,
     width: 300,
   },
   {
-    title: "关键词所在URL",
-    align: "center",
-    dataIndex: "positionUrl",
+    title: '关键词所在URL',
+    align: 'center',
+    dataIndex: 'positionUrl',
     width: 500,
   },
   {
-    title: "关键词类型",
-    align: "center",
-    dataIndex: "keywordType",
+    title: '关键词类型',
+    align: 'center',
+    dataIndex: 'keywordType',
     width: 230,
   },
   {
@@ -54,16 +49,16 @@ export const columns: BasicColumn[] = [
 //查询数据
 export const searchFormSchema: FormSchema[] = [
   {
-    label: "关键词",
+    label: '关键词',
     field: 'keywords',
     component: 'Input',
     //colProps: {span: 6},
   },
   {
-    label: "关键词类型",
+    label: '关键词类型',
     field: 'keywordType',
     component: 'JDictSelectTag',
-    componentProps:{
+    componentProps: {
       dictCode: 'keyword_type',
       placeholder: '请选择关键词类型',
       stringToNumber: true,
@@ -83,15 +78,15 @@ export const searchFormSchema: FormSchema[] = [
   //       { label: '前十页(TOP 100)', value: 10 },
   //     ],
   //   },
-    //colProps: {span: 6},
+  //colProps: {span: 6},
   // },
 ];
 //表单数据
 export const formSchema: FormSchema[] = [
   {
-    label: "关键词类型",
-    field: "keywordType",
-    component: "JDictSelectTag",
+    label: '关键词类型',
+    field: 'keywordType',
+    component: 'JDictSelectTag',
     componentProps: {
       dictCode: 'keyword_type',
       placeholder: '请选择关键词类型',
@@ -99,75 +94,71 @@ export const formSchema: FormSchema[] = [
     },
   },
   {
-    label: "关键词",
-    field: "keywords",
-    component: "Input",
-    dynamicRules: ({ model, schema }) => {
-      return [
-        { required: true, message: "请输入关键词!" }
-      ];
-    }
+    label: '关键词',
+    field: 'keywords',
+    component: 'Input',
+    dynamicRules: ({}) => {
+      return [{ required: true, message: '请输入关键词!' }];
+    },
   },
   {
-    label: "站点ID",
-    field: "siteCode",
-    component: "Input",
+    label: '站点ID',
+    field: 'siteCode',
+    component: 'Input',
     show: false,
     defaultValue: localStorage.getItem('siteCode'),
-    dynamicRules: ({ model, schema }) => {
-      return [
-        { required: true, message: "没有站点ID!" }
-      ];
+    dynamicRules: ({}) => {
+      return [{ required: true, message: '没有站点ID!' }];
     },
   },
   // TODO 主键隐藏字段,目前写死为ID
   {
-    label: "",
-    field: "id",
-    component: "Input",
-    show: false
-  }
+    label: '',
+    field: 'id',
+    component: 'Input',
+    show: false,
+  },
 ];
 
 // 高级查询数据
 export const superQuerySchema = {
-  keywords: { title: "关键词", order: 2, view: "text", type: "string" },
-  lastSearchTime: { title: "最新搜索时间", order: 5, view: "datetime", type: "string" },
+  keywords: { title: '关键词', order: 2, view: 'text', type: 'string' },
+  lastSearchTime: { title: '最新搜索时间', order: 5, view: 'datetime', type: 'string' },
   timerLastSearchTime: {
-    title: "定时器的最新搜索时间",
+    title: '定时器的最新搜索时间',
     order: 6,
-    view: "datetime",
-    type: "string"
-  },
-  status: { title: "0删除,1有效,2过期", order: 7, view: "number", type: "number" },
-  sourceId: { title: "数据复制源ID", order: 8, view: "number", type: "number" },
-  priority: { title: "关键词优先级(1:高;2:中;3:低)", order: 9, view: "number", type: "number" },
-  finishTime: { title: "SEO关键词优化完成时间", order: 10, view: "datetime", type: "string" },
-  optimizeProcess: { title: "优化进度(默认0)", order: 11, view: "number", type: "number" },
+    view: 'datetime',
+    type: 'string',
+  },
+  status: { title: '0删除,1有效,2过期', order: 7, view: 'number', type: 'number' },
+  sourceId: { title: '数据复制源ID', order: 8, view: 'number', type: 'number' },
+  priority: { title: '关键词优先级(1:高;2:中;3:低)', order: 9, view: 'number', type: 'number' },
+  finishTime: { title: 'SEO关键词优化完成时间', order: 10, view: 'datetime', type: 'string' },
+  optimizeProcess: { title: '优化进度(默认0)', order: 11, view: 'number', type: 'number' },
   optimizeStatus: {
-    title: "优化状态(0:未完成;1:已完成)",
+    title: '优化状态(0:未完成;1:已完成)',
     order: 12,
-    view: "number",
-    type: "number"
+    view: 'number',
+    type: 'number',
   },
-  keywordType: { title: "关键词类型", order: 13, view: "number", type: "number" },
-  lastRank: { title: "最近一次搜索排名", order: 14, view: "number", type: "number" },
+  keywordType: { title: '关键词类型', order: 13, view: 'number', type: 'number' },
+  lastRank: { title: '最近一次搜索排名', order: 14, view: 'number', type: 'number' },
   searchStatus: {
-    title: "搜索状态,0为普通状态,1为搜索进行中状态",
+    title: '搜索状态,0为普通状态,1为搜索进行中状态',
     order: 15,
-    view: "number",
-    type: "number"
+    view: 'number',
+    type: 'number',
   },
-  positionUrl: { title: "关键词所在URL", order: 16, view: "textarea", type: "string" },
+  positionUrl: { title: '关键词所在URL', order: 16, view: 'textarea', type: 'string' },
   relatedKeywordId: {
-    title: "相关关键词关联的关键词的id",
+    title: '相关关键词关联的关键词的id',
     order: 17,
-    view: "number",
-    type: "number"
+    view: 'number',
+    type: 'number',
   },
-  planId: { title: "关键词对应套餐的ID", order: 18, view: "text", type: "string" },
-  subscriptionId: { title: "订购表ID", order: 19, view: "text", type: "string" },
-  siteId: { title: "网站表ID", order: 20, view: "text", type: "string" }
+  planId: { title: '关键词对应套餐的ID', order: 18, view: 'text', type: 'string' },
+  subscriptionId: { title: '订购表ID', order: 19, view: 'text', type: 'string' },
+  siteId: { title: '网站表ID', order: 20, view: 'text', type: 'string' },
 };
 
 /**

Niektoré súbory nie sú zobrazené, pretože je v týchto rozdielových dátach zmenené mnoho súborov