Prechádzať zdrojové kódy

Merge branch 'pointsShop' of http://39.101.143.165:8090/wangxiaoqian/yelaixiang into pointsShop

MS-IOHQJGHXZHQD\Administrator 6 mesiacov pred
rodič
commit
ec647799f5

+ 55 - 28
src/api/points/rules_api.js

@@ -1,38 +1,65 @@
-import request from '@/utils/request'
+import request from '@/utils/request';
+
+/**
+ * 获取城市接口
+ * @param {Object} query - 等级和父级id
+ */
+export function getCity(query) {
+  return request({
+    url: '/area/select',
+    method: 'get',
+    params: query
+  })
+}
 /**
  * 获取活动列表的函数
  * @param {Object} query - 查询参数对象,包含查询条件
  */
 export function getActivityList(query) {
-  let res = {
-    "total": 4,
-    "rows": [
-      {
-        "activityName": "签到活动",
-        "activityType": "1",
-        "activityCity": "太原",
-        "activityStatus": "1",
-        "activityTime": '2026-1-1  -  2027-1-1',
-      },
-      {
-        "activityName": "新手任务",
-        "activityType": "2",
-        "activityCity": "太原",
-        "activityStatus": "3",
-        "activityTime": '长期有效',
-      },
-    ],
-    "code": 200,
-    "msg": "查询成功"
-  }
-  return new Promise((resolve, reject) => {
-    // 模拟网络延迟 1000ms
-    setTimeout(() => {
-      resolve(res)
-    }, 1000);
-  });
+  return request({
+    url: '/point/activity/page',
+    method: 'get',
+    params: query
+  })
+}
+
+/**
+ * 根据id获取积分活动详情
+ * @param {Object} query - 查询参数对象,包含查询条件
+ */
+export function getActivityById(query) {
+  console.log(query)
+  return request({
+    url: '/point/activity/'+query.id,
+    method: 'get',
+  })
 }
 
+/**
+ * 草稿、发布 - 提交(编辑)
+ * @param {Object} query - 查询参数对象,包含查询条件
+ */
+export function submitActivity(data) {
+  return request({
+    url: '/point/activity',
+    method: 'put',
+    data: data
+  })
+}
+
+/**
+* 草稿、发布 - 提交(编辑)
+* @param {Object} query - 查询参数对象,包含查询条件
+*/
+export function addActivity(data) {
+  return request({
+    url: '/point/activity',
+    method: 'post',
+    data: data
+  })
+}
+
+
 /**
  * 获取单一活动统计信息
  * @param {Object} query - 查询参数对象,包含查询条件

+ 1 - 1
src/components/tableCompontent/TableColumn.vue

@@ -262,7 +262,7 @@
         <span v-if="!$scopedSlots[itemCol.prop]">{{ scope.row[itemCol.prop] === '' ? '--' : scope.row[itemCol.prop] }}</span>
       </span>
       <span :style="`color:${itemCol.color}`" v-else>
-        {{ scope.row[itemCol.prop] === '' ? '--' : scope.row[itemCol.prop] }}
+        {{ scope.row[itemCol.prop] === null ? '--' : scope.row[itemCol.prop] }}
       </span>
     </template>
   </el-table-column>

+ 3 - 1
src/main.js

@@ -21,9 +21,10 @@ import { download } from '@/utils/request'
 
 import './assets/icons' // icon
 import './permission' // permission control
+
 import { getDicts } from "@/api/system/dict/data";
 import { getConfigKey } from "@/api/system/config";
-import { parseTime, resetForm, addDateRange,DateRange, selectDictLabel, selectDictLabels, handleTree } from "@/utils/ruoyi";
+import {useDict, parseTime, resetForm, addDateRange,DateRange, selectDictLabel, selectDictLabels, handleTree } from "@/utils/ruoyi";
 // 分页组件
 import Pagination from "@/components/Pagination";
 // 自定义表格工具组件
@@ -57,6 +58,7 @@ Vue.prototype.selectDictLabel = selectDictLabel
 Vue.prototype.selectDictLabels = selectDictLabels
 Vue.prototype.download = download
 Vue.prototype.handleTree = handleTree
+Vue.prototype.useDict = useDict
 
 import tinymce from 'tinymce';
 Vue.prototype.$tinymce = tinymce;

+ 1 - 0
src/utils/dict/index.js

@@ -31,3 +31,4 @@ export default function(Vue, options) {
     },
   })
 }
+

+ 13 - 1
src/utils/ruoyi.js

@@ -4,7 +4,6 @@
  * 通用js方法封装处理
  * Copyright (c) 2019 ylx
  */
-
 // 日期格式化
 export function parseTime(time, pattern) {
   if (arguments.length === 0 || !time) {
@@ -246,3 +245,16 @@ export function tansParams(params) {
 export function blobValidate(data) {
   return data.type !== 'application/json'
 }
+
+
+
+import { getDicts } from '@/api/system/dict/data'
+export async function useDict(...args) {
+  const res = {}
+  await Promise.all(args.map(async (d) => {
+      res[d] = [];
+      const resp = await getDicts(d);
+      res[d] = resp.data.map(p => ({ label: p.dictLabel, value: p.dictValue }));
+  }));
+  return res;
+}

+ 566 - 0
src/views/pointsManagement/pointsRules/compontents/Activity_editBox.vue

@@ -0,0 +1,566 @@
+<template>
+  <el-dialog
+    title="积分活动"
+    :visible.sync="pointsActivity"
+    width="900px"
+    :before-close="handleClose"
+    custom-class="activity-edit-dialog">
+{{form}}
+    <el-form :model="form" :rules="rules" ref="formRef" label-width="140px" class="activity-form">
+      <el-row :gutter="20">
+        <el-col :span="12">
+          <el-form-item label="活动名称" prop="name">
+            <el-input v-model="form.name" placeholder="请输入活动名称" :disabled="type === 'view'"></el-input>
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="活动简述" prop="description">
+            <el-input v-model="form.description" placeholder="请输入活动简述" :disabled="type === 'view'"></el-input>
+          </el-form-item>
+        </el-col>
+      </el-row>
+
+      <el-row :gutter="20">
+        <el-col :span="12">
+          <el-form-item label="活动城市" prop="cityCode">
+             <DictSelect v-model="form.cityCode" :dictOptions="cityOptions" placeholder="请选择" :disabled="type === 'view'"/>
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="活动类型" prop="activityType">
+            <DictSelect v-model="form.activityType" :dictOptions="activityTypeOption" placeholder="请选择" :disabled="type === 'view'" @change="handleActivityTypeChange"/>
+          </el-form-item>
+        </el-col>
+      </el-row>
+
+      <el-row :gutter="20">
+        <el-col :span="12">
+          <el-form-item label="活动时间" prop="isPermanent">
+            <el-radio-group v-model="form.isPermanent" :disabled="type === 'view'">
+              <el-radio label="1">长期有效</el-radio>
+              <el-radio label="0">指定时间</el-radio>
+            </el-radio-group>
+          </el-form-item>
+        </el-col>
+        <el-col :span="12" v-if="form.isPermanent == '0'">
+           <el-form-item label="指定时间" prop="dateRange">
+              <el-date-picker
+                v-model="form.dateRange"
+                type="daterange"
+                range-separator="→"
+                start-placeholder="开始日期"
+                end-placeholder="结束日期"
+                style="width: 100%"
+                :disabled="type === 'view'"
+                :picker-options="pickerOptions"
+                @change="handleDateChange"
+            ></el-date-picker>
+           </el-form-item>
+        </el-col>
+      </el-row>
+
+      <!-- 签到活动特有的内容 -->
+      <template v-if="form.activityType == '0'">
+        <el-row :gutter="20">
+          <el-col :span="12">
+            <el-form-item label="每日签到基础积分" prop="basePoints">
+              <el-input v-model="form.basePoints" type="number" placeholder="请输入" :disabled="type === 'view'"></el-input>
+            </el-form-item>
+          </el-col>
+        </el-row>
+
+        <el-row :gutter="20">
+          <el-col :span="24">
+            <el-form-item label="连续签到加成" prop="signRewardList">
+              <el-table :data="form.signRewardList" style="width: 100%" :disabled="type === 'view'" size="mini">
+                <el-table-column prop="continueDays" label="连续签到周期(天)">
+                  <template slot-scope="scope">
+                    <span v-if="type === 'view'">
+                      {{ scope.row.continueDays }}天
+                    </span>
+                    <el-input v-else v-model="scope.row.continueDays" type="number" placeholder="天数" @blur="updatePeriod(scope.$index, scope.row.continueDays)"></el-input>
+                  </template>
+                </el-table-column>
+                <el-table-column prop="rewardPoints" label="连续签到积分">
+                  <template slot-scope="scope">
+                    <span v-if="type === 'view'">
+                      {{ scope.row.rewardPoints }}
+                    </span>
+                    <el-input v-else v-model="scope.row.rewardPoints" type="number" placeholder="积分"></el-input>
+                  </template>
+                </el-table-column>
+                <el-table-column label="说明" width="280">
+                  <template slot-scope="scope">
+                    {{ getDescription(scope.$index) }}
+                  </template>
+                </el-table-column>
+                <el-table-column width="50">
+                  <template slot="header" slot-scope="scope">
+                    <span>
+                      <el-button v-if="type !== 'view' && form.signRewardList.length < 5" type="text" size="medium" @click="addPeriod" title="添加周期">
+                        <i class="el-icon-circle-plus-outline"></i>
+                      </el-button>
+                    </span>
+                  </template>
+                  <template slot-scope="scope">
+                    <el-button v-if="type !== 'view'" type="text" @click="deletePeriod(scope.$index)" title="删除周期">
+                        <i class="el-icon-remove-outline"></i>
+                      </el-button>
+                  </template>
+                </el-table-column>
+              </el-table>
+            </el-form-item>
+          </el-col>
+        </el-row>
+
+        <el-row :gutter="20">
+          <el-col :span="12">
+            <el-form-item label="断签规则">
+              <el-radio-group v-model="form.breakRule" :disabled="type === 'view'">
+                <el-radio :label="item.value" v-for="(item,index) in signRule" :key="index">{{ item.label }}</el-radio>
+              </el-radio-group>
+            </el-form-item>
+          </el-col>
+        </el-row>
+      </template>
+
+      <!-- 其他活动类型的内容 -->
+      <template v-else>
+        <el-row :gutter="20">
+          <el-col :span="24">
+            <el-form-item label="任务列表" prop="activityTaskList">
+              <el-table :data="form.activityTaskList" style="width: 100%" :disabled="type === 'view'" size="medium">
+                <el-table-column prop="taskName" label="任务名称" width="150">
+                  <template slot-scope="scope">
+                    <span>{{ scope.row.taskName }}</span>
+                  </template>
+                </el-table-column>
+                <el-table-column prop="triggerValue" label="触发条件" width="200">
+                  <template slot-scope="scope">
+                    <span v-if="type === 'view'">
+                      <span v-if="scope.row.taskName === '分享服务号' || scope.row.taskName === '浏览动态' || scope.row.taskName === '浏览商户'">
+                        点击
+                      </span>
+                       <template v-else>
+                          <span style="margin-right: 5px;">&gt;=</span> {{ scope.row.triggerValue }}
+                       </template>
+                    </span>
+                    <template v-else>
+                      <span v-if="scope.row.taskName === '分享服务号' || scope.row.taskName === '浏览动态' || scope.row.taskName === '浏览商户'">
+                        点击
+                      </span>
+                      <span v-else style="display: flex; align-items: center;">
+                        <template v-if="scope.row.status == 0">
+                           <span style="margin-right: 5px;">&gt;=</span>
+                          <el-input v-model="scope.row.triggerValue" type="number" placeholder="请输入" style="width: 80px"></el-input>
+                        </template>
+                        <span v-else>--</span>
+                      </span>
+                    </template>
+                  </template>
+                </el-table-column>
+                <el-table-column prop="rewardPoints" label="积分">
+                  <template slot-scope="scope">
+                    <span v-if="type === 'view'">{{ scope.row.rewardPoints }}</span>
+                    <template v-else>
+                      <el-input v-if="scope.row.status == 0" v-model="scope.row.rewardPoints" type="number" placeholder="请输入"></el-input>
+                      <span v-else>--</span>
+                    </template>
+                  </template>
+                </el-table-column>
+                <el-table-column prop="frequencyLimitValue" label="次数限制" width="120">
+                  <template slot-scope="scope">
+                    <span v-if="type === 'view'">{{ scope.row.frequencyLimitValue }}</span>
+                    <template v-else>
+                      <DictSelect v-if="scope.row.status == 0" v-model="scope.row.frequencyLimitValue" :dictOptions="taskLimitTimes" placeholder="请选择"/>
+                      <span v-else>--</span>
+                    </template>
+                  </template>
+                </el-table-column>
+                <el-table-column label="是否开启" width="120">
+                  <template slot-scope="scope">
+                    <el-switch v-model="scope.row.status" active-value="0"
+                               inactive-value="1" :disabled="type === 'view'"></el-switch>
+                  </template>
+                </el-table-column>
+              </el-table>
+            </el-form-item>
+          </el-col>
+        </el-row>
+      </template>
+    </el-form>
+
+    <div class="button-container" v-if="type !== 'view'">
+      <el-button @click="handleClose" class="cancel-btn">取消</el-button>
+      <el-button @click="handleSave('3')" class="cancel-btn">保存草稿</el-button>
+      <el-button type="primary" @click="handleSave('4')" class="confirm-btn">发布</el-button>
+    </div>
+    <div class="button-container" v-else>
+      <el-button type="primary" @click="handleClose" class="confirm-btn">关闭</el-button>
+    </div>
+  </el-dialog>
+</template>
+
+<script>
+import { getActivityById,submitActivity,addActivity } from "@/api/points/rules_api";
+export default {
+  name: "Activity_editBox",
+  props: ['activityTypeOption', 'cityOptions','taskLimitTimes','signRule'],
+  data() {
+    return {
+      pointsActivity: false,
+      type: '',
+      minDate: null,
+      form: {
+        name: '',
+        description: '',
+        cityCode: '',
+        activityType: '',
+        isPermanent: '',
+        startTime: '',
+        endTime: '',
+        dateRange: '',
+        basePoints: '',
+        signRewardList: [
+          { continueDays: '3', rewardPoints: '' },
+        ],
+        breakRule: '0', // 0: 断签重置, 1: 保留进度
+        activityTaskList: []
+      },
+      pickerOptions: {
+        onPick: ({ maxDate, minDate }) => {
+          if (minDate) {
+            this.minDate = minDate;
+          }
+          if (maxDate) {
+            this.minDate = null;
+          }
+        },
+        disabledDate: (time) => {
+          if (this.minDate) {
+            const minTime = this.minDate.getTime();
+            const sevenDaysLater = minTime + 6 * 24 * 60 * 60 * 1000; // 6天后(总共7天)
+            return time.getTime() < minTime || (time.getTime() < sevenDaysLater && time.getTime() > minTime);
+          }
+          return false;
+        }
+      },
+      rules: {
+        name: [
+          { required: true, message: '请输入活动名称', trigger: 'blur' },
+          { min: 2, max: 18, message: '请输入2-18个字符', trigger: 'blur' }
+        ],
+        description: [
+          { required: true, message: '请输入活动简述', trigger: 'blur' },
+          { min: 2, max: 30, message: '请输入2-30个字符', trigger: 'blur' }
+        ],
+        cityCode: [
+          { required: true, message: '请选择活动城市', trigger: 'change' }
+        ],
+        activityType: [
+          { required: true, message: '请选择活动类型', trigger: 'change' }
+        ],
+        basePoints: [
+          { required: true, message: '请输入基础积分', trigger: 'blur' },
+          { validator: (rule, value, callback) => {
+              if (Number(value) < 0) {
+                callback(new Error('基础积分不能小于0'));
+              } else {
+                callback();
+              }
+            },
+            trigger: 'blur'
+          }
+        ],
+        signRewardList: [
+          { validator: (rule, value, callback) => {
+              if (!value || value.length === 0) {
+                callback(new Error('请添加连续签到加成'));
+                return;
+              }
+
+              for (let i = 0; i < value.length; i++) {
+                const bonus = value[i];
+                if (!bonus.continueDays || Number(bonus.continueDays) <= 0) {
+                  callback(new Error('连续签到周期必须大于0'));
+                  return;
+                }
+                if (!bonus.rewardPoints || Number(bonus.rewardPoints) <= 0) {
+                  callback(new Error('连续签到积分必须大于0'));
+                  return;
+                }
+              }
+
+              // 检查连续签到周期总和是否超过活动总天数
+              const totalDays = this.getTotalDays();
+              if (this.form.isPermanent == '0' && totalDays > 0) {
+                const totalPeriod = value.reduce((sum, item) => sum + Number(item.continueDays), 0);
+                if (totalPeriod > totalDays) {
+                  callback(new Error('连续签到周期总和不能超过活动总天数'));
+                  return;
+                }
+              }
+
+              callback();
+            },
+            trigger: 'change'
+          }
+        ],
+        dateRange: [
+          { required: true, message: '请选择活动时间', trigger: 'change' }
+        ],
+        activityTaskList: [
+          { validator: (rule, value, callback) => {
+              for (let i = 0; i < value.length; i++) {
+                const task = value[i];
+                // 只在任务开启的情况下才校验
+                if (task.status == '0') {
+                  // 验证完成订单和充值任务的触发条件
+                  if ((task.taskName === '完成订单' || task.taskName === '充值任务') && (!task.triggerValue || Number(task.triggerValue) <= 0)) {
+                    callback(new Error('触发条件必须大于0'));
+                    return;
+                  }
+                  // 验证所有任务的积分
+                  if (!task.rewardPoints || Number(task.rewardPoints) <= 0) {
+                    callback(new Error('积分必须大于0'));
+                    return;
+                  }
+                }
+              }
+              callback();
+            },
+            trigger: 'change'
+          }
+        ]
+      },
+    }
+  },
+  methods: {
+    async getActivityInfo(row) {
+      const res = await getActivityById({id: row.id});
+      return res.data.detail;
+    },
+    getDefaultTasks() {
+      return [
+        { taskName: '完成订单', triggerValue: '', rewardPoints: '', frequencyLimitValue: '0', status: '1' },
+        { taskName: '充值任务', triggerValue: '', rewardPoints: '', frequencyLimitValue: '0', status: '1' },
+        { taskName: '分享服务号', triggerValue: '点击', rewardPoints: '', frequencyLimitValue: '0', status: '1' },
+        { taskName: '浏览动态', triggerValue: '点击', rewardPoints: '', frequencyLimitValue: '0', status: '1' },
+        { taskName: '浏览商户', triggerValue: '点击', rewardPoints: '', frequencyLimitValue: '0', status: '1' }
+      ];
+    },
+    getTotalDays() {
+      if (this.form.isPermanent == '0' && this.form.startTime && this.form.endTime) {
+        const start = new Date(this.form.startTime);
+        const end = new Date(this.form.endTime);
+        return Math.floor((end - start) / (1000 * 60 * 60 * 24)) + 1;
+      }
+      return 0;
+    },
+    async getRow(row, type) {
+      /** type ==== 添加:add 复制:copy 编辑:edit 查看:view */
+      this.type = type;
+      this.resetForm();
+      if (type !== 'add') {
+        const data = await this.getActivityInfo(row);
+        if (type === 'copy') {
+          const { id, ...copyData } = data;
+          this.form = copyData;
+        } else {
+          this.form = { ...data };
+        }
+        this.form.isPermanent = this.form.isPermanent?.toString();
+        this.form.breakRule = this.form.breakRule?.toString();
+        this.form.dateRange = [this.form.startTime, this.form.endTime];
+      }
+      this.pointsActivity = true;
+    },
+    handleClose() {
+      this.pointsActivity = false;
+    },
+    resetForm() {
+      this.form = {
+        name: '',
+        description: '',
+        cityCode: '',
+        activityType: '0',
+        isPermanent: '1',
+        startTime: '',
+        endTime: '',
+        dateRange: '',
+        basePoints: '',
+        signRewardList: [
+          { continueDays: '3', rewardPoints: '' },
+        ],
+        breakRule: '0',
+        activityTaskList: this.getDefaultTasks()
+      };
+    },
+    handleDateChange(val) {
+      if (val) {
+        this.form.startTime = val[0];
+        this.form.endTime = val[1];
+      } else {
+        this.form.startTime = '';
+        this.form.endTime = '';
+      }
+      this.handleActivityTypeChange();
+    },
+    deletePeriod(index) {
+      if (this.form.signRewardList.length <= 1) {
+        this.$message.warning('至少保留一个连续签到周期');
+        return;
+      }
+      this.form.signRewardList.splice(index, 1);
+      this.updatePeriod();
+    },
+    handleActivityTypeChange() {
+      // 重置相关内容
+      if (this.form.activityType == '0') {
+        // 签到活动
+        this.form.basePoints = '';
+        this.form.signRewardList = [
+          { continueDays: '3', rewardPoints: ''},
+        ];
+        this.form.breakRule = '0';
+      } else {
+        // 其他活动
+        this.form.activityTaskList = this.getDefaultTasks();
+      }
+    },
+    addPeriod() {
+      const totalDays = this.getTotalDays();
+      const currentTotalPeriod = this.form.signRewardList.reduce((sum, item) => {
+        return sum + (Number(item.continueDays) || 0);
+      }, 0);
+
+      if (this.form.isPermanent == '0' && totalDays > 0 && currentTotalPeriod >= totalDays) {
+        this.$message.warning('连续签到周期总和不能超过活动总天数');
+        return;
+      }
+
+      this.form.signRewardList.push({
+        continueDays: '',
+        rewardPoints: ''
+      });
+    },
+    updatePeriod() {
+      // 触发表单验证
+      this.$refs.formRef.validateField('signRewardList');
+    },
+    getDescription(index) {
+      let totalPeriodDays = 0;
+      let totalPoints = 0;
+
+      for (let i = 0; i <= index; i++) {
+        totalPeriodDays += Number(this.form.signRewardList[i].continueDays) || 0;
+        totalPoints += Number(this.form.signRewardList[i].rewardPoints) || 0;
+      }
+
+      const basePoints = Number(this.form.basePoints) || 0;
+      const finalPoints = totalPoints + basePoints;
+
+      if (!totalPeriodDays || !finalPoints) {
+        return '--';
+      }
+
+      return `连续签到 ${totalPeriodDays} 天后,继续签到可获得 ${finalPoints} 积分`;
+    },
+    validateForm(callback) {
+      this.$refs.formRef.validate((valid) => {
+        if (valid) {
+          callback();
+        }
+      });
+    },
+    handleSave(type) {
+      //3:草稿 4:发布
+      this.validateForm(() => {
+        this.form = this.DateRange(this.form,this.form.dateRange || [],['startTime','endTime'])
+        let paramsUrl = ['add','copy'].includes(this.type) ? addActivity : submitActivity;
+          paramsUrl({
+          ...this.form,
+          status:type
+        }).then(response => {
+          this.$message.success('草稿已保存');
+          this.pointsActivity = false;
+        })
+      });
+    },
+  }
+}
+</script>
+
+<style scoped lang="scss">
+.activity-edit-dialog {
+  .el-dialog__header {
+    padding: 20px;
+    border-bottom: 1px solid #e8e8e8;
+
+    .el-dialog__title {
+      font-size: 16px;
+      font-weight: 600;
+      color: #303133;
+    }
+  }
+
+  .el-dialog__body {
+    padding: 25px;
+  }
+
+  .el-dialog__footer {
+    padding: 15px 20px;
+    border-top: 1px solid #e8e8e8;
+  }
+}
+
+.activity-form {
+  .form-tip {
+    font-size: 12px;
+    color: #f56c6c;
+    margin-top: 5px;
+  }
+
+  .el-form-item {
+    margin-bottom: 20px;
+  }
+
+  .el-table {
+    margin-top: 10px;
+    border: 1px solid #ebeef5;
+    border-radius: 4px;
+  }
+
+  .el-table__header-wrapper {
+    background-color: #f5f7fa;
+  }
+
+  .el-table th {
+    font-weight: 600;
+  }
+}
+
+.button-container {
+  display: flex;
+  justify-content: flex-end;
+  margin-top: 30px;
+
+  .cancel-btn {
+    margin-right: 10px;
+  }
+
+  .confirm-btn {
+    min-width: 100px;
+  }
+}
+
+/* 隐藏number输入框的上下小按钮 */
+::v-deep input[type="number"]::-webkit-inner-spin-button,
+::v-deep input[type="number"]::-webkit-outer-spin-button {
+  -webkit-appearance: none;
+  margin: 0;
+}
+::v-deep input[type="number"] {
+  -moz-appearance: textfield;
+}
+</style>

+ 104 - 87
src/views/pointsManagement/pointsRules/index.vue

@@ -1,63 +1,69 @@
 <template>
   <div class="app-container">
-        <el-form :model="queryParams" ref="queryRef" size="small" :inline="true" v-show="showSearch" label-width="68px">
-          <el-form-item label="活动类型" prop="activityType">
-            <DictSelect v-model="queryParams.activityType" :dictOptions="activityTypeOption" placeholder="请选择"/>
-          </el-form-item>
-          <el-form-item label="城市" prop="activityCity">
-            <DictSelect v-model="queryParams.activityCity" :dictOptions="navigateMenuOption" placeholder="请选择"/>
-          </el-form-item>
-          <el-form-item label="状态" prop="activityStatus">
-            <DictSelect v-model="queryParams.activityStatus" :dictOptions="navigateMenuOption" placeholder="请选择"/>
-          </el-form-item>
-          <el-form-item label="活动时间" prop="dateRange">
-            <el-date-picker
-              v-model="queryParams.dateRange"
-              style="width: 240px"
-              value-format="yyyy-MM-dd"
-              type="daterange"
-              range-separator="-"
-              start-placeholder="开始日期"
-              end-placeholder="结束日期"
-            ></el-date-picker>
-          </el-form-item>
-          <el-form-item>
-            <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
-            <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
-          </el-form-item>
-        </el-form>
+    <el-form :model="queryParams" ref="queryRef" size="small" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="活动类型" prop="activityType">
+        <DictSelect v-model="queryParams.activityType" :dictOptions="activityTypeOption" placeholder="请选择"/>
+      </el-form-item>
+      <el-form-item label="城市" prop="cityCode">
+        <DictSelect v-model="queryParams.cityCode" :dictOptions="cityOptions" placeholder="请选择"/>
+      </el-form-item>
+      <el-form-item label="状态" prop="status">
+        <DictSelect v-model="queryParams.status" :dictOptions="statusOption" placeholder="请选择"/>
+      </el-form-item>
+      <el-form-item label="活动时间" prop="dateRange">
+        <el-date-picker
+          v-model="queryParams.dateRange"
+          style="width: 240px"
+          value-format="yyyy-MM-dd"
+          type="daterange"
+          range-separator="-"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期"
+        ></el-date-picker>
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
 
-        <el-row :gutter="10" class="mb8">
-          <el-col :span="1.5">
-            <el-button
-              type="primary"
-              plain
-              size="mini"
-              @click="handleRuleAdd"
-            >新增积分活动</el-button>
-            <el-button
-              type="primary"
-              plain
-              size="mini"
-              @click="setExpiration"
-            >积分时效</el-button>
-          </el-col>
-          <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
-        </el-row>
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="primary"
+          plain
+          size="mini"
+          @click="handleRule('','add')"
+        >新增积分活动</el-button>
+        <el-button
+          type="primary"
+          plain
+          size="mini"
+          @click="setExpiration"
+        >积分时效</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
 
     <tableCompontent ref="tableRef" height="72vh" :loading="loading" :tableData="list" :columnData="columnData">
-      <template v-slot:activityStatus="row">
-        <span v-if="row.activityStatus === '1'" style="color: #85c91e">进行中</span>
-        <span v-else-if="row.activityStatus === '3'" style="color: red">已结束</span>
-        <span v-else>--</span>
+      <template v-slot:status="row">
+        <span v-if="row.status == '0'" style="color: #909399">未开始</span>
+        <span v-else-if="row.status == '1'" style="color: #67c23a">进行中</span>
+        <span v-else-if="row.status == '2'" style="color: #f56c6c">已结束</span>
+        <span v-else-if="row.status == '3'" style="color: #e6a23c">草稿</span>
       </template>
+      <template v-slot:activityTime="row">
+        <span v-if="row.isPermanent == '0'"> {{ parseTime(row.startTime, '{y}-{m}-{d}') }} - {{ parseTime(row.endTime, '{y}-{m}-{d}') }}</span>
+        <span v-else>长期有效</span>
+      </template>
+
       <template v-slot:nickName="row">
         <el-link type="primary" slot="reference" @click="viewStatistics(row)">查看统计</el-link>
       </template>
       <template v-slot:operation="row">
-        <el-button size="mini" type="text" @click="handleView(row)">详情</el-button>
-        <el-button size="mini" type="text" @click="handleEdit(row)">编辑</el-button>
-        <el-button size="mini" type="text" @click="handleCopy(row)">复制</el-button>
+        <el-button size="mini" type="text" @click="handleRule(row,'view')">详情</el-button>
+        <el-button size="mini" type="text" @click="handleRule(row,'edit')">编辑</el-button>
+        <el-button size="mini" type="text" @click="handleRule(row,'copy')">复制</el-button>
       </template>
     </tableCompontent>
 
@@ -72,36 +78,38 @@
     <expiration-points ref="expirationPointsRef" />
     <!-- 活动统计 -->
     <activity-statistics ref="activityStatisticsRef" />
+    <!-- 活动编辑 -->
+    <activity-edit-box ref="activityEditBoxRef"
+                       :activityTypeOption="activityTypeOption"
+                       :cityOptions="cityOptions"
+                       :taskLimitTimes="taskLimitTimes"
+                       :signRule="signRule"/>
   </div>
 </template>
 
 <script>
-import { getActivityList } from "@/api/points/rules_api";
+import { getCity,getActivityList } from "@/api/points/rules_api";
 import tableCompontent from "@/components/tableCompontent/index.vue";
 import listMixin from '@/utils/listMixin';
 import ExpirationPoints from "./compontents/Expiration_points.vue";
 import ActivityStatistics from "./compontents/Activity_statistics.vue";
+import activityEditBox from "./compontents/Activity_editBox.vue";
 export default {
   name: "pointsRules",
   mixins: [listMixin],
   components: {
     tableCompontent,
     ExpirationPoints,
-    ActivityStatistics
+    ActivityStatistics,
+    activityEditBox
   },
   data() {
     return {
       // 用户表格数据
       list: null,
-      activityTypeOption:[
-        {label:'签到任务',value:'1'},
-        {label:'新手任务',value:'2'},
-      ],
-      navigateMenuOption:[
-        {label:'测试数据',value:'1'},
-        {label:'测试数据1',value:'2'},
-        {label:'测试数据2',value:'3'}
-      ],
+      activityTypeOption:[],
+      cityOptions: [],
+      statusOption:[],
       columnData:[
         {
           prop: 'seq',
@@ -112,7 +120,7 @@ export default {
           fixed: 'left'
         },
         {
-          prop: 'activityName',
+          prop: 'name',
           label: '活动名称',
           align:'center',
         },
@@ -124,12 +132,14 @@ export default {
           option:[]
         },
         {
-          prop: 'activityCity',
+          prop: 'cityCode',
           label: '覆盖城市',
           align:'center',
+          type:'find',
+          option:[]
         },
         {
-          prop: 'activityStatus',
+          prop: 'status',
           label: '状态',
           align:'center',
           type: 'diy',
@@ -138,6 +148,7 @@ export default {
           prop: 'activityTime',
           label: '活动时间',
           align:'center',
+          type: 'diy',
         },
         {
           prop: 'nickName',
@@ -154,32 +165,52 @@ export default {
           width: 120
         },
       ],
+      taskLimitTimes:[],
+      signRule:[]
     };
   },
   created() {
+    this.getOptionList();
     this.queryParams = {
       ...this.queryParams,
       activityType:'',
-      activityCity:'',
-      activityStatus:'',
+      cityCode:'',
+      status:'',
       dateRange:[],
     }
     this.isImmediateLoad = false;
     this.getListUrl = getActivityList;
-    // 或者设置自定义数据处理函数
     this.customProcessDataFun = (val) => {
-      // 自定义处理查询参数
-      this.queryParams = this.DateRange(this.queryParams,val.dateRange || [],['startTime','endTime'],'s')
+      this.queryParams = this.DateRange(this.queryParams,val.dateRange || [],['startTime','endTime'])
     };
   },
   mounted(){
-    this.columnData.find(item => item.prop === 'activityType').option = this.activityTypeOption;
     this.handleQuery();
   },
   methods: {
-    /** 新增操作 */
-    handleRuleAdd() {
-
+    async getOptionList(){
+      //获取活动类型,获取活动状态
+      const {activity_type,activity_status, task_limit_times,sign_rule} = await this.useDict('activity_type','activity_status','task_limit_times','sign_rule');
+      this.activityTypeOption = activity_type;
+      this.statusOption = activity_status;
+      this.taskLimitTimes = task_limit_times;
+      this.signRule = sign_rule;
+      //获取城市
+      const cityOption = await getCity({
+        level:'2',
+        parentCode:'140000'
+      })
+      this.cityOptions = cityOption.data.map(p => ({ label: p.name, value: p.code }));
+      this.columnData.find(item => item.prop === 'activityType').option = this.activityTypeOption;
+      this.columnData.find(item => item.prop === 'cityCode').option = this.cityOptions;
+    },
+    /** 添加:add 复制:copy 编辑:edit 查看:view */
+    handleRule(row,type) {
+      if (type === 'edit' && row.status === '1') {
+        this.$message.warning('活动进行中,不可编辑');
+        return;
+      }
+      this.$refs.activityEditBoxRef?.getRow(row,type);
     },
     /** 积分时效 */
     setExpiration() {
@@ -189,20 +220,6 @@ export default {
     viewStatistics(row){
       this.$refs.activityStatisticsRef?.openDrawer(row);
     },
-    /** 查看详情 */
-    handleView(row) {
-
-    },
-
-    /** 编辑 */
-    handleEdit(row) {
-
-    },
-
-    /** 复制 */
-    handleCopy(row) {
-
-    },
   }
 };
 </script>