瀏覽代碼

Merge remote-tracking branch 'origin/master'

Zenas 1 周之前
父節點
當前提交
ad8f7b3a11

+ 29 - 26
src/views/adweb/enquiry/AdwebEnquiry.data.ts

@@ -4,7 +4,7 @@ import { rules } from '@/utils/helper/validator';
 export const columns: BasicColumn[] = [
   {
     title: '站点名称',
-    align: 'left',
+    align: 'center',
     dataIndex: 'siteName',
     defaultHidden: true,
   },
@@ -15,12 +15,12 @@ export const columns: BasicColumn[] = [
   },
   {
     title: '邮箱',
-    align: 'left',
+    align: 'center',
     dataIndex: 'fromEmail',
   },
   {
     title: 'WhatsApp',
-    align: 'left',
+    align: 'center',
     dataIndex: 'whatsApp',
     customRender: function ({ text }) {
       if (text == null || text == '' || text == undefined) {
@@ -33,7 +33,7 @@ export const columns: BasicColumn[] = [
 
   {
     title: '手机号',
-    align: 'left',
+    align: 'center',
     dataIndex: 'phone',
     customRender: function ({ text }) {
       if (text == null || text == '' || text == undefined) {
@@ -46,7 +46,7 @@ export const columns: BasicColumn[] = [
 
   {
     title: '来源IP',
-    align: 'left',
+    align: 'center',
     dataIndex: 'fromIp',
     defaultHidden: true,
 
@@ -61,13 +61,12 @@ export const columns: BasicColumn[] = [
 
   {
     title: '状态',
-    align: 'left',
+    align: 'center',
     dataIndex: 'readStatus',
   },
   {
     title: '询盘详情',
     align: 'left',
-
     dataIndex: 'details',
   },
   // {
@@ -78,14 +77,18 @@ export const columns: BasicColumn[] = [
   {
     title: '来源页面',
     align: 'left',
-
     dataIndex: 'fromPage',
   },
   {
     title: '分类',
-    align: 'left',
+    align: 'center',
     dataIndex: 'userEffective',
   },
+  // {
+  //   title: '询盘审核进度',
+  //   align: 'center',
+  //   dataIndex: 'verifyProgress',
+  // },
   {
     title: '来源国家',
     align: 'left',
@@ -100,13 +103,13 @@ export const columns: BasicColumn[] = [
   },
   {
     title: '来源插件',
-    align: 'left',
+    align: 'center',
     dataIndex: 'pluginName',
     defaultHidden: true,
   },
   {
     title: '询盘时间',
-    align: 'left',
+    align: 'center',
     dataIndex: 'recordCtime',
     customRender: function ({ text }) {
       return !text ? '' : text.length > 16 ? text.substr(0, 16) : text;
@@ -114,7 +117,7 @@ export const columns: BasicColumn[] = [
   },
   {
     title: '创建时间',
-    align: 'left',
+    align: 'center',
     dataIndex: 'ctime',
     customRender: function ({ text }) {
       return !text ? '' : text.length > 16 ? text.substr(0, 16) : text;
@@ -131,24 +134,24 @@ export const columns: BasicColumn[] = [
 export const wasteColumns: BasicColumn[] = [
   {
     title: '站点名称',
-    align: 'left',
+    align: 'center',
     dataIndex: 'siteName',
     defaultHidden: true,
   },
   {
     title: '姓名',
-    align: 'left',
+    align: 'center',
     dataIndex: 'contact',
   },
   {
     title: '邮箱',
-    align: 'left',
+    align: 'center',
     dataIndex: 'fromEmail',
   },
 
   {
     title: '手机号',
-    align: 'left',
+    align: 'center',
     dataIndex: 'phone',
     customRender: function ({ text }) {
       if (text == null || text == '' || text == undefined) {
@@ -161,7 +164,7 @@ export const wasteColumns: BasicColumn[] = [
 
   {
     title: '来源IP',
-    align: 'left',
+    align: 'center',
     dataIndex: 'fromIp',
 
     customRender: function ({ text }) {
@@ -175,12 +178,12 @@ export const wasteColumns: BasicColumn[] = [
 
   {
     title: '状态',
-    align: 'left',
+    align: 'center',
     dataIndex: 'readStatus',
   },
   {
     title: '询盘详情',
-    align: 'left',
+    align: 'center',
 
     dataIndex: 'details',
   },
@@ -191,18 +194,18 @@ export const wasteColumns: BasicColumn[] = [
   // },
   {
     title: '来源页面',
-    align: 'left',
+    align: 'center',
 
     dataIndex: 'fromPage',
   },
   {
     title: '询盘类型',
-    align: 'left',
+    align: 'center',
     dataIndex: 'wasteEnquiryType',
   },
   {
     title: '来源国家',
-    align: 'left',
+    align: 'center',
     dataIndex: 'countryName',
     customRender: function ({ text }) {
       if (text == null || text == '' || text == undefined) {
@@ -214,7 +217,7 @@ export const wasteColumns: BasicColumn[] = [
   },
   {
     title: '询盘时间',
-    align: 'left',
+    align: 'center',
 
     dataIndex: 'recordCtime',
     customRender: function ({ text }) {
@@ -223,7 +226,7 @@ export const wasteColumns: BasicColumn[] = [
   },
   {
     title: '创建时间',
-    align: 'left',
+    align: 'center',
     dataIndex: 'ctime',
     customRender: function ({ text }) {
       return !text ? '' : text.length > 16 ? text.substr(0, 16) : text;
@@ -252,7 +255,7 @@ export const formSchema: FormSchema[] = [
     field: 'email',
     component: 'Input',
     required: true,
-    dynamicRules: ({ model, schema }) => {
+    dynamicRules: ({}) => {
       return [{ ...rules.rule('email', false)[0], trigger: 'blur' }];
     },
   },
@@ -260,7 +263,7 @@ export const formSchema: FormSchema[] = [
     label: '手机号码',
     field: 'phone',
     component: 'Input',
-    dynamicRules: ({ model, schema }) => {
+    dynamicRules: ({}) => {
       return [{ pattern: /^1[3456789]\d{9}$/, message: '手机号码格式有误', trigger: 'blur' }];
     },
   },

+ 23 - 14
src/views/adweb/enquiry/AdwebEnquiryList.vue

@@ -111,7 +111,7 @@
 
       <!-- 操作动作  -->
       <template #action="{ record }">
-        <div style="padding: 5px 8px; display: flex; justify-content: space-around">
+        <div style="padding: 5px 8px; display: flex; justify-content: left">
           <a-tag v-if="isForwardSite" color="blue" @click="forwardDetail(record)" style="cursor: pointer"> 转发 </a-tag>
           <a-tag color="purple" @click="showEnquiryDetail(record)" style="cursor: pointer"> 详情 </a-tag>
           <a-popconfirm
@@ -128,7 +128,7 @@
             color="blue"
             v-if="record.visitId !== null && record.visitId !== '' && record.visitId !== undefined"
             style="cursor: pointer"
-            @click="enquiryTrack(record)"
+            @click="showEnquiryTrack(record)"
           >
             访问记录
           </a-tag>
@@ -211,6 +211,11 @@
             <div v-else>--</div>
           </a-popover>
         </div>
+
+        <!-- 审核进度条-->
+        <div v-if="column.dataIndex == 'verifyProgress'">
+          <a-progress :size="10" :showInfo="true" :percent="50" />
+        </div>
       </template>
     </BasicTable>
     <!-- 表单区域 -->
@@ -242,6 +247,9 @@
 
     <!--跟踪记录-->
     <enquiry-track-record ref="enquiryTrackRecordRef" />
+
+    <!--站点访问记录-->
+    <enquiry-track ref="enquiryTrackRef" />
   </div>
 </template>
 
@@ -255,7 +263,7 @@
   import { computed, nextTick, onBeforeMount, onMounted, reactive, ref } from 'vue';
   import { BasicTable } from '/@/components/Table';
   import { useListPage } from '/@/hooks/system/useListPage';
-  import { columns, superQuerySchema } from './AdwebEnquiry.data';
+  import { columns } from './AdwebEnquiry.data';
   import { batchDelete, deleteOne, getExportUrl, getImportUrl, list } from './AdwebEnquiry.api';
   import AdwebEnquiryModal from './components/AdwebEnquiryModal.vue';
   import { useUserStore } from '/@/store/modules/user';
@@ -269,6 +277,7 @@
   import enquiryTrackRecord from '@/views/adweb/enquiry/modules/enquiryTrackRecord.vue';
   import { RoleEnum } from '@/enums/roleEnum';
   import dayjs, { Dayjs } from 'dayjs';
+  import EnquiryTrack from '@/views/adweb/enquiry/modules/enquiryTrack.vue';
 
   const dateFormat = 'YYYY-MM-DD';
   type RangeValue = [Dayjs, Dayjs];
@@ -288,13 +297,15 @@
   //注册table数据
   const { prefixCls, tableContext, onExportXls, onImportXls } = useListPage({
     tableProps: {
-      title: '询盘信息存储表单',
+      title: '询盘信息',
       api: list,
       columns,
       canResize: false,
       useSearchForm: false,
       actionColumn: {
         width: 180,
+        maxWidth: 220,
+        minWidth: 180,
         fixed: 'right',
       },
       striped: true,
@@ -376,6 +387,9 @@
   // 跟踪记录
   const enquiryTrackRecordRef = ref(null);
 
+  // 访问记录
+  const enquiryTrackRef = ref();
+
   onBeforeMount(() => {
     siteCode.value = localStorage.getItem('siteCode');
     getTurnInquiryCode();
@@ -761,17 +775,12 @@
     }
   }
 
-  // 高级查询配置
-  const superQueryConfig = reactive(superQuerySchema);
+  async function showEnquiryTrack(record) {
+    await nextTick();
 
-  /**
-   * 高级查询事件
-   */
-  function handleSuperQuery(params) {
-    Object.keys(params).map((k) => {
-      queryParam[k] = params[k];
-    });
-    searchQuery();
+    if (enquiryTrackRef.value && enquiryTrackRef.value.init) {
+      enquiryTrackRef.value.init(record);
+    }
   }
 
   /**

+ 19 - 0
src/views/adweb/enquiry/AdwebEnquiryVerifyFlow.vue

@@ -0,0 +1,19 @@
+<template>
+  <a-card :bordered="false" title="询盘审核流程模板">
+    <flow-process-edit ref="processEditRef" />
+  </a-card>
+</template>
+
+<script lang="ts" setup>
+  import '/@/assets/less/common.less';
+  import FlowProcessEdit from '/@/views/adweb/modules/flowProcessEdit.vue';
+  import { nextTick, onMounted, ref } from 'vue';
+
+  const processEditRef = ref();
+  onMounted(() => {
+    nextTick(() => {
+      processEditRef.value.onClose();
+      processEditRef.value.init({}, 'build');
+    });
+  });
+</script>

+ 26 - 84
src/views/adweb/enquiry/AdwebWasteEnquiryList.vue

@@ -85,7 +85,7 @@
 
       <!-- 操作动作  -->
       <template #action="{ record }">
-        <div style="padding: 5px 8px; display: flex; justify-content: space-around">
+        <div style="padding: 5px 8px; display: flex; justify-content: left">
           <a-tag v-if="isForwardSite" color="blue" @click="forwardDetail(record)" style="cursor: pointer"> 转发 </a-tag>
           <a-tag color="purple" @click="showEnquiryDetail(record)" style="cursor: pointer"> 详情 </a-tag>
           <a-popconfirm
@@ -102,7 +102,7 @@
             color="blue"
             v-if="record.visitId !== null && record.visitId !== '' && record.visitId !== undefined"
             style="cursor: pointer"
-            @click="enquiryTrack(record)"
+            @click="showEnquiryTrack(record)"
           >
             访问记录
           </a-tag>
@@ -200,6 +200,9 @@
 
     <!--跟踪记录-->
     <enquiry-track-record ref="enquiryTrackRecordRef" />
+
+    <!--站点访问记录-->
+    <enquiry-track ref="enquiryTrackRef" />
   </div>
 </template>
 
@@ -208,8 +211,8 @@
   import { nextTick, onBeforeMount, onMounted, reactive, ref } from 'vue';
   import { BasicTable } from '/@/components/Table';
   import { useListPage } from '/@/hooks/system/useListPage';
-  import { wasteColumns, superQuerySchema } from './AdwebEnquiry.data';
-  import { batchDelete, deleteOne, getExportUrl, getImportUrl, list } from './AdwebEnquiry.api';
+  import { wasteColumns } from './AdwebEnquiry.data';
+  import { batchDelete, getExportUrl, getImportUrl, list } from './AdwebEnquiry.api';
   import AdwebEnquiryModal from './components/AdwebEnquiryModal.vue';
   import { useUserStore } from '/@/store/modules/user';
   import { getAction, postAction } from '@/api/manage/manage';
@@ -218,33 +221,36 @@
 
   // 过滤日期范围
   import dayjs, { Dayjs } from 'dayjs';
-  const dateFormat = 'YYYY-MM-DD';
-  type RangeValue = [Dayjs, Dayjs];
-  // 过滤日期范围
-  let rangeDate = ref<RangeValue>();
-
   import { filterOption } from 'ant-design-vue/es/vc-mentions/src/util';
   import enquiryDetail from '@/views/adweb/enquiry/modules/enquiryDetail.vue';
   import XpRecycleBinModal from '@/views/adweb/system/modules/XpRecycleBinModal.vue';
   import blackList from '@/views/adweb/enquiry/modules/blackList.vue';
   import enquiryTrackRecord from '@/views/adweb/enquiry/modules/enquiryTrackRecord.vue';
+  import EnquiryTrack from '@/views/adweb/enquiry/modules/enquiryTrack.vue';
+
+  const dateFormat = 'YYYY-MM-DD';
+  type RangeValue = [Dayjs, Dayjs];
+  // 过滤日期范围
+  let rangeDate = ref<RangeValue>();
 
   const formRef = ref();
   const queryParam = reactive<any>({});
-  const toggleSearchStatus = ref<boolean>(false);
+
   const registerModal = ref();
   const selectSiteRef = ref(null);
   const { createMessage } = useMessage();
   //注册table数据
   const { prefixCls, tableContext, onExportXls, onImportXls } = useListPage({
     tableProps: {
-      title: '询盘信息存储表单',
+      title: '垃圾询盘信息',
       api: list,
       columns: wasteColumns,
       canResize: false,
       useSearchForm: false,
       actionColumn: {
         width: 180,
+        maxWidth: 220,
+        minWidth: 180,
         fixed: 'right',
       },
       striped: true,
@@ -341,6 +347,10 @@
 
   // 跟踪记录
   const enquiryTrackRecordRef = ref();
+
+  // 访问记录
+  const enquiryTrackRef = ref();
+
   const userStore = useUserStore();
 
   onBeforeMount(() => {
@@ -681,48 +691,12 @@
     }
   }
 
-  // 高级查询配置
-  const superQueryConfig = reactive(superQuerySchema);
-
-  /**
-   * 高级查询事件
-   */
-  function handleSuperQuery(params) {
-    Object.keys(params).map((k) => {
-      queryParam[k] = params[k];
-    });
-    searchQuery();
-  }
-
-  /**
-   * 新增事件
-   */
-  function handleAdd() {
-    registerModal.value.disableSubmit = false;
-    registerModal.value.add();
-  }
-
-  /**
-   * 编辑事件
-   */
-  function handleEdit(record: Recordable) {
-    registerModal.value.disableSubmit = false;
-    registerModal.value.edit(record);
-  }
-
-  /**
-   * 详情
-   */
-  function handleDetail(record: Recordable) {
-    registerModal.value.disableSubmit = true;
-    registerModal.value.edit(record);
-  }
+  async function showEnquiryTrack(record) {
+    await nextTick();
 
-  /**
-   * 删除事件
-   */
-  async function handleDelete(record) {
-    await deleteOne({ id: record.id }, handleSuccess);
+    if (enquiryTrackRef.value && enquiryTrackRef.value.init) {
+      enquiryTrackRef.value.init(record);
+    }
   }
 
   /**
@@ -740,38 +714,6 @@
   }
 
   /**
-   * 操作栏
-   */
-  function getTableAction(record) {
-    return [
-      {
-        label: '编辑',
-        onClick: handleEdit.bind(null, record),
-      },
-    ];
-  }
-
-  /**
-   * 下拉操作栏
-   */
-  function getDropDownAction(record) {
-    return [
-      {
-        label: '详情',
-        onClick: handleDetail.bind(null, record),
-      },
-      {
-        label: '删除',
-        popConfirm: {
-          title: '是否确认删除',
-          confirm: handleDelete.bind(null, record),
-          placement: 'topLeft',
-        },
-      },
-    ];
-  }
-
-  /**
    * 查询
    */
   function searchQuery() {

+ 102 - 108
src/views/adweb/enquiry/modules/enquiryTrack.vue

@@ -1,141 +1,135 @@
 <template>
-  <a-modal
-    :title="title"
-    :width="width"
-    v-model="modalVisible"
-    centered
-    :closable="true"
-    :keyboard="false"
-    :maskClosable="false"
-    width="50%"
-  >
-    <template slot="footer">
+  <a-modal :title="title" :width="width" v-model="modalVisible" centered :closable="true" :keyboard="false" :maskClosable="false" width="50%">
+    <template #footer>
       <a-button @click="handleCancel">关闭</a-button>
     </template>
 
     <div class="wrap">
-<!--      <p style="font-size: 13px;color: #999">展示数据为记录询盘的前后七天时间范围!</p>-->
+      <!--      <p style="font-size: 13px;color: #999">展示数据为记录询盘的前后七天时间范围!</p>-->
       <a-spin :spinning="spinning" tip="正在获取访问记录数据">
-        <a-empty v-if="trackData.length == 0"></a-empty>
-        <a-row v-for="(item,index) in trackData" :key="index">
+        <a-empty v-if="trackData.length == 0" />
+        <a-row v-for="(item, index) in trackData" :key="index">
           <a-col :span="24" class="c1">
             <span class="time">{{ item.serverDatePrettyFirstAction }} - {{ item.serverTimePrettyFirstAction }}</span>
-            <span>访问终端:{{item.deviceType}}</span>
+            <span>访问终端:{{ item.deviceType }}</span>
             <span>来源媒介:{{ item.referrerTypeName }}</span>
             <span>操作系统:{{ item.operatingSystemCode }}</span>
           </a-col>
           <a-col :span="24">
-            <p class="t1">{{item.actionDetails.length}}页面分析- {{item.visitDurationPretty}}<span style="float: right">停留时间</span></p>
-            <a-steps direction="vertical" >
-              <a-step status="finish" v-for="(child,index2) in item.actionDetails" :key="index2" v-if="child.pageTitle != null">
-                <div slot="title">
-                  <span>{{ child.pageTitle }}</span> <a-tag style="margin-left: 15px" v-if="filterGetMax(child.timeSpent,index) && item.actionDetails.length > 2" color="orange">停留最久</a-tag>
-                </div>
-                <div slot="description">
-                  <a :href="child.url" target="_blank">{{ child.url }}</a>
-                  <span style="float: right">{{child.timeSpentPretty}}</span>
-                </div>
-                <a-icon slot="icon" type="folder" />
+            <p class="t1">{{ item.actionDetails.length }}页面分析- {{ item.visitDurationPretty }}<span style="float: right">停留时间</span></p>
+            <a-steps direction="vertical">
+              <a-step status="finish" v-for="(child, index2) in item.actionDetails" :key="index2" v-if="child.pageTitle != null">
+                <template #title>
+                  <div>
+                    <span>{{ child.pageTitle }}</span>
+                    <a-tag style="margin-left: 15px" v-if="filterGetMax(child.timeSpent, index) && item.actionDetails.length > 2" color="orange"
+                      >停留最久</a-tag
+                    >
+                  </div>
+                </template>
+                <template #description>
+                  <div>
+                    <a :href="child.url" target="_blank">{{ child.url }}</a>
+                    <span style="float: right">{{ child.timeSpentPretty }}</span>
+                  </div>
+                </template>
+                <template #icon>
+                  <a-icon type="folder" />
+                </template>
               </a-step>
             </a-steps>
           </a-col>
-          <a-divider></a-divider>
+          <a-divider />
         </a-row>
       </a-spin>
-
-
     </div>
-
   </a-modal>
 </template>
 
 <script>
-import { getAction } from '/@/api/manage/manage'
-
-export default {
-  name: 'enquiryTrack',
-  data () {
-    return {
-      title:"访问记录",
-      width:800,
-      modalVisible: false,
-      disableSubmit: false,
-      record:{},
-      trackData:[],
-      maxArr:[],
-      spinning:false
-
-    }
-  },
-
-  filters:{
-
-  },
-
-
-  methods: {
-    init (record) {
-      this.modalVisible=true
-      this.maxArr = []
-      this.record = record
-      this.spinning = true
-      getAction('/adweb/adwebEnquiry/getMatomoWebTrackFromEnquiryId?id=' + record.id).then(res => {
-        this.spinning = false
-          if(res.code == 200){
-            this.trackData = res.result
-            this.getMAx()
-          }
-      })
+  import { getAction } from '/@/api/manage/manage';
+
+  export default {
+    name: 'EnquiryTrack',
+
+    filters: {},
+    data() {
+      return {
+        title: '访问记录',
+        width: 800,
+        modalVisible: false,
+        disableSubmit: false,
+        record: {},
+        trackData: [],
+        maxArr: [],
+        spinning: false,
+      };
     },
 
-    filterGetMax(value,index) {
-      for(let i in this.maxArr){
-          if(value == this.maxArr[index]){
-            return true
-          }else{
-            return false
+    methods: {
+      init(record) {
+        this.modalVisible = true;
+        this.maxArr = [];
+        this.record = record;
+        this.spinning = true;
+        getAction('/adweb/adwebEnquiry/getMatomoWebTrackFromEnquiryId?id=' + record.id).then((res) => {
+          this.spinning = false;
+          if (res.code == 200) {
+            this.trackData = res.result;
+            this.getMAx();
           }
-      }
-    },
-
-
-    handleCancel () {
-      this.$emit('close');
-      this.modalVisible = false;
+        });
+      },
+
+      filterGetMax(value, index) {
+        for (let i in this.maxArr) {
+          if (value == this.maxArr[index]) {
+            return true;
+          } else {
+            return false;
+          }
+        }
+      },
+
+      handleCancel() {
+        this.$emit('close');
+        this.modalVisible = false;
+      },
+
+      getMAx() {
+        let trankData = this.trackData;
+        for (let i in trankData) {
+          this.maxArr.push(
+            Math.max.apply(
+              Math,
+              trankData[i].actionDetails.map((item) => {
+                return item.timeSpent;
+              })
+            )
+          );
+        }
+      },
     },
-
-    getMAx(){
-      let trankData = this.trackData
-      for(let i in trankData){
-        this.maxArr.push(Math.max.apply(Math,trankData[i].actionDetails.map(item => { return item.timeSpent })))
-      }
-    }
-
-  }
-}
+  };
 </script>
 
-
 <style lang="less" scoped>
-
-
-
-.wrap{
-  .c1{
-    span{
-      color: #333;
-      &:not(:last-child){
-        margin-right: 35px;
-      }
-      &.time{
-        font-size: 20px;
+  .wrap {
+    .c1 {
+      span {
+        color: #333;
+        &:not(:last-child) {
+          margin-right: 35px;
+        }
+        &.time {
+          font-size: 20px;
+        }
       }
     }
+    .t1 {
+      font-size: 14px;
+      color: #333;
+      margin: 20px 0 10px;
+    }
   }
-  .t1{
-    font-size: 14px;
-    color: #333;
-    margin: 20px 0 10px;
-  }
-}
 </style>

+ 2 - 2
src/views/adweb/enquiry/modules/enquiryTrackRecord.vue

@@ -49,9 +49,9 @@
 </template>
 
 <script>
-  import { getAction, postAction, postActionForm } from '/@/api/manage/manage';
-  import Qs from 'qs';
+  import { getAction, postActionForm } from '/@/api/manage/manage';
   import { useMessage } from '@/hooks/web/useMessage';
+
   const { createMessage } = useMessage();
 
   export default {

+ 241 - 0
src/views/adweb/modules/flowProcessEdit.vue

@@ -0,0 +1,241 @@
+<template>
+  <div>
+    <a-row :gutter="16" style="margin-bottom: 20px">
+      <a-col :span="24">
+        <a-button type="primary" @click="submitAll" :loading="loading" style="margin-right: 6px"> 保存流程 </a-button>
+        <a-button @click="addNew" :loading="loading"> 新增节点 </a-button>
+      </a-col>
+    </a-row>
+    <a-table
+      :columns="columns"
+      :rowKey="(record, index) => index"
+      :data-source="data"
+      :pagination="false"
+      :scroll="{ x: true }"
+      :loading="tableLoading"
+      class="j-table-force-nowrap"
+      size="middle"
+    >
+      <template v-for="col in ['name', 'description', 'timeDesc', 'proportion']" #[col]="text, record, index">
+        <div :key="col">
+          <a-input v-if="record.editable" style="margin: -5px 0" :value="text" @change="(e) => handleChange(e.target.value, record.key, col)" />
+          <template v-else>
+            {{ text }}
+          </template>
+        </div>
+      </template>
+      <template #proportionTitle>
+        <span
+          >权重
+          <a-tooltip placement="top">
+            <template #title>
+              <span>权重之和应为100</span>
+            </template>
+            <a-icon type="question-circle" />
+          </a-tooltip>
+        </span>
+      </template>
+      <template #id="text, record, index">
+        <a-tag color="pink" @click="up(record, index)" style="cursor: pointer" :class="index == 0 ? 'disabled' : ''">
+          <a-icon type="arrow-up" />
+        </a-tag>
+        <a-tag color="blue" @click="down(record, index)" style="cursor: pointer" :class="index == data.length - 1 ? 'disabled' : ''">
+          <a-icon type="arrow-down" />
+        </a-tag>
+      </template>
+      <template #action="text, record, index">
+        <div class="editable-row-operations">
+          <span v-if="record.editable">
+            <a @click="() => save(record.key)">保存</a>
+          </span>
+          <span v-else>
+            <a :disabled="editingKey !== ''" @click="() => edit(record.key)">编辑</a>
+            <a-divider type="vertical" />
+            <a :disabled="editingKey !== ''" @click="() => deleteRow(index)">删除</a>
+          </span>
+        </div>
+      </template>
+    </a-table>
+  </div>
+</template>
+
+<script lang="ts" setup>
+  import { getAction, postAction } from '/@/api/manage/manage';
+  import { reactive, ref } from 'vue';
+  import { useMessage } from '@/hooks/web/useMessage';
+  const columns = [
+    {
+      title: '节点名称',
+      dataIndex: 'name',
+      scopedSlots: { customRender: 'name' },
+    },
+    {
+      title: '节点描述',
+      dataIndex: 'description',
+      scopedSlots: { customRender: 'description' },
+    },
+    {
+      title: '预计时间',
+      dataIndex: 'timeDesc',
+      scopedSlots: { customRender: 'timeDesc' },
+    },
+    {
+      dataIndex: 'proportion',
+      scopedSlots: { customRender: 'proportion', title: 'proportionTitle' },
+    },
+    {
+      title: '排序',
+      dataIndex: 'id',
+      scopedSlots: { customRender: 'id' },
+    },
+    {
+      title: '操作',
+      dataIndex: 'action',
+      scopedSlots: { customRender: 'action' },
+    },
+  ];
+
+  let data = reactive([{}]);
+  const editingKey = ref('');
+  const hostId = ref('');
+  const tableLoading = ref(false);
+  const loading = ref(false);
+  let record = reactive({});
+  let cacheData = reactive([{}]);
+
+  const { createMessage } = useMessage();
+  function submitAll() {
+    let d = data;
+    let proportion = 0;
+    for (let i in d) {
+      proportion += parseInt(d[i].proportion);
+    }
+    if (parseInt(proportion) !== 100) {
+      createMessage.warn('权重之和应为100');
+      return;
+    }
+    loading.value = true;
+    // for(let i in d){
+    //   delete d[i].key
+    // }
+    postAction('/adweb/executeNode/saveFlowTemplate', d, 120000)
+      .then((res) => {
+        loading.value = false;
+        if (res.code == 200) {
+          createMessage.success('保存成功');
+        } else {
+          createMessage.warn(res.message);
+        }
+      })
+      .catch((e) => {
+        createMessage.warn('保存数据失败!');
+      });
+  }
+  function addNew() {
+    data.push({
+      createTime: null,
+      delFlag: 0,
+      description: '',
+      finTime: null,
+      finUid: null,
+      hostId: hostId,
+      id: '',
+      name: '',
+      nodeType: 3,
+      proportion: null,
+      sort: 1,
+      status: null,
+      timeDesc: null,
+      type: 1,
+      key: data.length,
+    });
+    cacheData = data;
+  }
+  //排序
+  function up(r, i) {
+    if (i == 0) {
+      return;
+    }
+    data.splice(i - 1, 0, data[i]);
+    data.splice(i + 1, 1);
+  }
+  function down(r, i) {
+    if (i == data.length - 1) {
+      return;
+    }
+    data.splice(i + 2, 0, data[i]);
+    data.splice(i, 1);
+  }
+  function deleteRow(i) {
+    data.splice(i, 1);
+  }
+  function onClose() {
+    data = [];
+  }
+  function init(r, t) {
+    record = r;
+    if (t == 'seo') {
+      url = '/adweb/executeNode/querySEOTemplateFlow?planId=' + r.id;
+    } else {
+      url = '/adweb/executeNode/querySiteBuildTemplateFlow';
+    }
+    showStep();
+  }
+  function showStep() {
+    let that = this;
+    that.tableLoading = true;
+    getAction(that.url)
+      .then((res) => {
+        that.tableLoading = false;
+        if (res.success) {
+          res.result.map((item, index) => {
+            that.data.push(Object.assign({}, item, { key: index }));
+            cacheData = data;
+            hostId.value = res.result[0].hostId;
+          });
+        }
+      })
+      .catch((e) => {
+        createMessage.warn('获取数据失败!');
+      });
+  }
+  function handleChange(value, key, column) {
+    const newData = [...data];
+    const target = newData.filter((item) => key === item.key)[0];
+    if (target) {
+      target[column] = value;
+      data = newData;
+    }
+  }
+  function edit(key) {
+    const newData = [...data];
+    const target = newData.filter((item) => key === item.key)[0];
+    editingKey.value = key;
+    if (target) {
+      target.editable = true;
+      data = newData;
+    }
+  }
+  function save(key) {
+    const newData = [...data];
+    const newCacheData = [...cacheData];
+    const target = newData.filter((item) => key === item.key)[0];
+    const targetCache = newCacheData.filter((item) => key === item.key)[0];
+    if (target && targetCache) {
+      delete target.editable;
+      data = newData;
+      Object.assign(targetCache, target);
+      cacheData = newCacheData;
+    }
+    editingKey.value = '';
+  }
+
+  defineExpose({ onClose, init });
+</script>
+
+<style scoped lang="less">
+  .ant-tag.disabled {
+    cursor: no-drop !important;
+    opacity: 0.3;
+  }
+</style>

+ 13 - 7
src/views/adweb/site/AdwebSiteList.vue

@@ -163,7 +163,7 @@
     <!-- 自动化嵌入GTM 代码     -->
     <gtm-add ref="gtmRef" />
     <!--SEO流程-->
-    <seo-process ref="seoProcessRef" :visible="seoProcessVisible" :title="processTitle" @close="closeProcess" @reload="reload" />
+    <site-process ref="siteProcessRef" :visible="seoProcessVisible" :title="processTitle" @close="closeProcess" @reload="reload" />
     <google-ads-modal ref="googleAdsModalRef" @success="reload" />
     <facebook-modal ref="faceBookModalRef" @success="reload" />
     <Sohoeb2bOrder ref="sohoeb2bOrderRef" @reload="reload" />
@@ -172,14 +172,14 @@
 </template>
 
 <script lang="ts" name="adweb-adwebSite" setup>
-  import { computed, onBeforeMount, reactive, ref } from 'vue';
+  import { computed, nextTick, onBeforeMount, reactive, ref } from 'vue';
   import { BasicTable, TableAction } from '/@/components/Table';
   import { useListPage } from '/@/hooks/system/useListPage';
   import { columns, superQuerySchema } from './AdwebSite.data';
   import { batchDelete, deleteOne, getExportUrl, getImportUrl, list, saveOrUpdate } from './AdwebSite.api';
   import AdwebSiteModal from './components/AdwebSiteModal.vue';
   import { useUserStore } from '/@/store/modules/user';
-  import SeoProcess from '@/views/adweb/site/components/SeoProcess.vue';
+  import SiteProcess from '@/views/adweb/site/components/SiteProcess.vue';
   import JInput from '@/components/Form/src/jeecg/components/JInput.vue';
   import JSearchSelect from '@/components/Form/src/jeecg/components/JSearchSelect.vue';
   import GtmAdd from '@/views/adweb/site/components/GtmAdd.vue';
@@ -201,7 +201,7 @@
   const userStore = useUserStore();
   const processTitle = ref('');
   const seoProcessVisible = ref(false);
-  const seoProcessRef = ref();
+  const siteProcessRef = ref();
   const sohoeb2bOrderRef = ref();
   const siteReleaseRef = ref();
   const gtmRef = ref();
@@ -240,6 +240,10 @@
       title: 'adweb站点配置表单',
       api: list,
       columns,
+      defSort: {
+        column: 'utime',
+        order: 'desc',
+      },
       canResize: false,
       useSearchForm: true,
       showTableSetting: true,
@@ -493,8 +497,8 @@
   function handleProcess(record, type) {
     seoProcessVisible.value = true;
     processTitle.value = record.name;
-    seoProcessRef.value.init(record, type);
-    seoProcessRef.value.isCustomer = true;
+    siteProcessRef.value.init(record, type);
+    siteProcessRef.value.isCustomer = true;
   }
 
   function closeProcess() {
@@ -502,7 +506,9 @@
   }
 
   function bindGoogleAds(record) {
-    googleAdsModalRef.value.init({ record });
+    nextTick(() => {
+      googleAdsModalRef.value.init({ record });
+    });
   }
 
   function addFaceBook(record) {

+ 19 - 14
src/views/adweb/site/components/GoogleAdsModal.vue

@@ -5,16 +5,16 @@
 </template>
 
 <script lang="ts" setup>
-  import { ref } from 'vue';
+  import { nextTick, ref } from 'vue';
   import { BasicDrawer, useDrawerInner } from '/@/components/Drawer';
-  import { BasicForm, useForm } from '/@/components/Form';
+  import { BasicForm, FormSchema, useForm } from '/@/components/Form';
   import { useMessage } from '/@/hooks/web/useMessage';
   import { getGoogleAdsAccount, bindGoogleAdsAccount } from '../AdwebSite.api';
 
   const emit = defineEmits(['success', 'register']);
   const { createMessage } = useMessage();
 
-  const formSchema = [
+  const formSchema: FormSchema[] = [
     {
       field: 'googleAdsAccount',
       label: 'Google Ads帐号',
@@ -64,8 +64,10 @@
   }
 
   // Add this method to handle initialization
-  const init = async (data: { record: Recordable }) => {
-    resetFields();
+  const init = (data: { record: Recordable }) => {
+    nextTick(() => {
+      resetFields();
+    });
     setDrawerProps({ visible: true, confirmLoading: true });
 
     try {
@@ -74,17 +76,20 @@
         siteCode: data.record.code,
       };
 
-      // 初始化默认写入siteCode
-      setFieldsValue({
-        siteCode: data.record.code,
-      });
-      const res = await getGoogleAdsAccount(params);
-      if (res) {
+      nextTick(() => {
+        // 初始化默认写入siteCode
         setFieldsValue({
-          googleAdsAccount: res.customerId,
-          apiRefreshToken: res.refreshToken,
+          siteCode: data.record.code,
         });
-      }
+      });
+      getGoogleAdsAccount(params).then((res) => {
+        if (res) {
+          setFieldsValue({
+            googleAdsAccount: res.customerId,
+            apiRefreshToken: res.refreshToken,
+          });
+        }
+      });
     } catch (error) {
       createMessage.error('获取Google Ads账号信息失败');
       console.error(error);

+ 0 - 0
src/views/adweb/site/components/SeoProcess.vue → src/views/adweb/site/components/SiteProcess.vue


+ 1 - 1
src/views/adweb/theme/AdwebTheme.data.ts

@@ -76,7 +76,7 @@ export const formSchema: FormSchema[] = [
     dynamicRules: ({ model, schema }) => {
       return [{ ...rules.existCheckRule('adweb_site', 'code', model, schema, false, '该临时站点不存在')[0], trigger: 'blur' }];
     },
-    helpMessage: '请输入已经存在的临时站点code,系统将会自动生成该模板站点,如果站点code为空,将会创建仅带图片的模板',
+    helpMessage: '请输入已经存在的临时站点code,系统将会自动生成该模板站点,如果站点code为空,将会创建仅带图片的模板',
     //自定义提示属性,需要结合helpMessage一起使用
     helpComponentProps: {
       maxWidth: '200px',

+ 16 - 3
src/views/adweb/theme/AdwebThemeList.vue

@@ -29,7 +29,7 @@
                     </a>
                     <div class="Content">
                       <a-button class="fl" block @click="visit(item, index)">模板预览</a-button>
-                      <a-button class="fl" block @click="handleEdit(item)">编辑模板</a-button>
+                      <a-button v-if="isAdmin" class="fl" block @click="handleEdit(item)">编辑模板</a-button>
                       <a-button v-if="checkUrl(item.domain)" type="primary" block class="fr" @click="createSite(item)">创建站点</a-button>
                     </div>
                   </div>
@@ -78,13 +78,15 @@
   import { getAction } from '/@/api/manage/manage';
   import $ from 'jquery';
 
-  import { nextTick, onMounted, reactive, ref } from 'vue';
+  import { computed, nextTick, onMounted, reactive, ref } from 'vue';
   import { useMessage } from '@/hooks/web/useMessage';
   import AdwebCreateSite from '@/views/adweb/theme/components/AdwebCreateSite.vue';
   import { useGlobSetting } from '@/hooks/setting';
   import AdwebThemeModal from '@/views/adweb/theme/components/AdwebThemeModal.vue';
+  import { RoleEnum } from '@/enums/roleEnum';
+  import { useUserStore } from '@/store/modules/user';
   const globSetting = useGlobSetting();
-
+  const userStore = useUserStore();
   const url = reactive({
     list: '/adweb/adwebTheme/list',
   });
@@ -125,6 +127,17 @@
 
   const { createMessage } = useMessage();
 
+  const isAdmin = computed(() => {
+    return (
+      userStore.getRoleList.includes(RoleEnum.ADMIN) ||
+      userStore.getRoleList.includes(RoleEnum.ADWEB_ADMIN) ||
+      userStore.getRoleList.includes(RoleEnum.SEO_ADMIN) ||
+      userStore.getRoleList.includes(RoleEnum.ADWEB_SITE_MANAGER) ||
+      userStore.getRoleList.includes(RoleEnum.ADWEB_SEO_MANAGER) ||
+      userStore.getRoleList.includes(RoleEnum.ADWEB_CHANNEL_ADMIN)
+    );
+  });
+
   onMounted(() => {
     getTemplateList();
   });

+ 1 - 1
src/views/system/tenant/tenant.data.ts

@@ -496,7 +496,7 @@ export const tenantUserSchema: FormSchema[] = [
     field: 'selectedroles',
     component: 'Input',
     componentProps: {
-      placeholder: 'adweb会员',
+      placeholder: 'VIP会员',
     },
     dynamicDisabled: ({ values }) => {
       return true;