Procházet zdrojové kódy

1. IOS切支付
2. 权限开关
3. 实名开关

ith5 před 6 měsíci
rodič
revize
9f6309de71

+ 2 - 2
src/views/login.vue

@@ -61,8 +61,8 @@ const handleSubmit = async ({ values, errors }) => {
     :style="{ background: appStore.mode === 'dark' ? '#2e2e30e3' : '' }"
   >
     <h3 class="login-logo">
-      <img src="/logo.png" alt="logo" />
-      <span>{{ $title }}</span>
+      <!-- <img src="/logo.png" alt="logo" />
+      <span>{{ $title }}</span> -->
     </h3>
 
     <div

+ 2 - 2
src/views/system/dept/index.vue

@@ -18,11 +18,11 @@
             />
           </a-form-item>
         </a-col>
-        <a-col :sm="8" :xs="24">
+        <!-- <a-col :sm="8" :xs="24">
           <a-form-item field="create_time" label="时间范围">
             <a-range-picker v-model="searchForm.create_time" />
           </a-form-item>
-        </a-col>
+        </a-col> -->
       </template>
       <!-- 搜索区 end -->
 

+ 6 - 7
src/views/system/user/index.vue

@@ -38,7 +38,7 @@
               />
             </a-form-item>
           </a-col>
-          <a-col :sm="8" :xs="24">
+          <!-- <a-col :sm="8" :xs="24">
             <a-form-item field="email" label="邮箱">
               <a-input
                 v-model="searchForm.email"
@@ -46,8 +46,8 @@
                 allow-clear
               />
             </a-form-item>
-          </a-col>
-          <a-col :sm="16" :xs="24">
+          </a-col> -->
+          <!-- <a-col :sm="16" :xs="24">
             <a-form-item field="create_time" label="注册时间">
               <a-range-picker
                 v-model="searchForm.create_time"
@@ -55,7 +55,7 @@
                 style="width: 100%"
               />
             </a-form-item>
-          </a-col>
+          </a-col> -->
           <a-col :sm="8" :xs="24">
             <a-form-item field="status" label="状态">
               <sa-select
@@ -330,13 +330,12 @@ const options = reactive({
 
 // SaTable 列配置
 const columns = reactive([
-  { title: "头像", dataIndex: "avatar", width: 75 },
   { title: "账户", dataIndex: "username", width: 130 },
   { title: "昵称", dataIndex: "nickname", width: 120 },
   { title: "手机", dataIndex: "phone", width: 150 },
-  { title: "邮箱", dataIndex: "email", width: 200 },
+  // { title: "邮箱", dataIndex: "email", width: 200 },
   { title: "状态", dataIndex: "status", width: 100 },
-  { title: "工作台", dataIndex: "dashboard", width: 100 },
+  // { title: "工作台", dataIndex: "dashboard", width: 100 },
   { title: "注册时间", dataIndex: "create_time", width: 180 },
 ]);
 

+ 0 - 0
src/views/v1/api/center/common.js → src/views/v1/api/common.js


+ 0 - 0
src/views/v1/api/center/game.js → src/views/v1/api/game.js


+ 0 - 0
src/views/v1/api/center/gameMain.js → src/views/v1/api/gameMain.js


+ 67 - 0
src/views/v1/api/iosPayWay.js

@@ -0,0 +1,67 @@
+import { request } from '@/utils/request.js'
+
+/**
+ * ios切支付 API接口
+ */
+export default {
+
+  /**
+   * 数据列表
+   * @returns
+   */
+  getPageList(params = {}) {
+    return request({
+      url: '/v1/center/IosPayWay/index',
+      method: 'get',
+      params
+    })
+  },
+
+  /**
+   * 添加数据
+   * @returns
+   */
+  save(params = {}) {
+    return request({
+      url: '/v1/center/IosPayWay/save',
+      method: 'post',
+      data: params
+    })
+  },
+
+  /**
+   * 更新数据
+   * @returns
+   */
+  update(id, data = {}) {
+    return request({
+      url: '/v1/center/IosPayWay/update?id=' + id,
+      method: 'put',
+      data
+    })
+  },
+
+  /**
+   * 读取数据
+   * @returns
+   */
+  read(id) {
+    return request({
+      url: '/v1/center/IosPayWay/read?id=' + id,
+      method: 'get'
+    })
+  },
+
+  /**
+   * 删除数据
+   * @returns
+   */
+  destroy(data) {
+    return request({
+      url: '/v1/center/IosPayWay/destroy',
+      method: 'delete',
+      data
+    })
+  },
+
+}

+ 65 - 0
src/views/v1/api/qxSwitch.js

@@ -0,0 +1,65 @@
+import { request } from "@/utils/request.js";
+
+/**
+ * ios切支付 API接口
+ */
+export default {
+  /**
+   * 数据列表
+   * @returns
+   */
+  getPageList(params = {}) {
+    return request({
+      url: "/v1/center/QxSwitch/index",
+      method: "get",
+      params,
+    });
+  },
+
+  /**
+   * 添加数据
+   * @returns
+   */
+  save(params = {}) {
+    return request({
+      url: "/v1/center/QxSwitch/save",
+      method: "post",
+      data: params,
+    });
+  },
+
+  /**
+   * 更新数据
+   * @returns
+   */
+  update(id, data = {}) {
+    return request({
+      url: "/v1/center/QxSwitch/update?id=" + id,
+      method: "put",
+      data,
+    });
+  },
+
+  /**
+   * 读取数据
+   * @returns
+   */
+  read(id) {
+    return request({
+      url: "/v1/center/QxSwitch/read?id=" + id,
+      method: "get",
+    });
+  },
+
+  /**
+   * 删除数据
+   * @returns
+   */
+  destroy(data) {
+    return request({
+      url: "/v1/center/QxSwitch/destroy",
+      method: "delete",
+      data,
+    });
+  },
+};

+ 5 - 1
src/views/v1/center/game/cp-info.vue

@@ -27,6 +27,9 @@
         <a-form-item label="pay_key">
           <a-input v-model="cp_info.pay_key" readonly />
         </a-form-item>
+        <a-form-item label="h5地址" v-if="cp_info.os == '5'">
+          <a-input v-model="cp_info.channel_h5_url" readonly />
+        </a-form-item>
       </a-form>
     </a-space>
   </component>
@@ -63,7 +66,8 @@ const handleOk = async () => {
 appid:${cp_info.value.appid}
 appkey:${cp_info.value.appkey}
 login_key:${cp_info.value.login_key}
-pay_key:${cp_info.value.pay_key}`;
+pay_key:${cp_info.value.pay_key}
+${cp_info.value.os == "5" ? `h5地址:${cp_info.value.channel_h5_url}` : ""}`;
 
   try {
     await tool.copy(copyText);

+ 85 - 36
src/views/v1/center/game/edit.vue

@@ -1,7 +1,7 @@
 <template>
   <component
     is="a-modal"
-    :width="tool.getDevice() === 'mobile' ? '100%' : '600px'"
+    :width="tool.getDevice() == 'mobile' ? '100%' : '600px'"
     v-model:visible="visible"
     :title="title"
     :mask-closable="false"
@@ -26,11 +26,8 @@
       </a-form-item>
       <a-form-item label="游戏名称" field="name">
         <a-input v-model="formData.name" placeholder="请输入游戏名称" />
-        <template #extra>
-          <div>末尾加备注的括号请用英文字符</div>
-        </template>
       </a-form-item>
-      <a-form-item label="平台" field="os">
+      <a-form-item label="游戏平台" field="os">
         <sa-select
           v-model="formData.os"
           dict="os"
@@ -38,75 +35,105 @@
           allow-clear
         />
       </a-form-item>
-      <a-form-item
-        label="h5游戏地址"
-        field="cp_h5_url"
-        v-if="formData.os === '5'"
-      >
-        <a-input v-model="formData.cp_h5_url" placeholder="请输入h5游戏地址" />
-      </a-form-item>
+
       <a-form-item label="分成比例" field="divide">
         <a-input-number
           v-model="formData.divide"
           placeholder="请输入分成比例"
         />
       </a-form-item>
-      <a-form-item label="苹果内购分成比例" field="ios_divide">
+      <a-form-item
+        label="内购分成比例"
+        field="ios_divide"
+        v-if="formData.os == '2'"
+      >
         <a-input-number
           v-model="formData.ios_divide"
           placeholder="请输入苹果内购分成比例"
         />
       </a-form-item>
-      <a-form-item label="主游戏" field="main_game_id">
+      <a-form-item label="游戏实名" field="realname_switch">
+        <sa-select
+          v-model="formData.realname_switch"
+          dict="realname_switch"
+          placeholder="请选择游戏实名"
+          allow-clear
+        />
+      </a-form-item>
+      <a-divider />
+      <a-form-item label="游戏KEY" field="main_game_id">
         <a-select
           v-model="formData.main_game_id"
           :options="gameOptions"
           placeholder="请选择主游戏"
           allow-clear
+          @change="handleMainGameChange"
         />
       </a-form-item>
-      <a-form-item label="游戏发货规则" field="cp_callback_type">
+      <a-form-item label="游戏发货规则" field="cp_callback_type" hidden>
         <sa-radio v-model="formData.cp_callback_type" dict="cp_callback_type" />
       </a-form-item>
-      <a-form-item label="包名" field="package_name">
+      <a-form-item label="游戏包名" field="package_name">
         <a-input
           v-model="formData.package_name"
           placeholder="安装包的包名,IOS与过包技术确认后填写"
         />
         <template #extra>
-          <div>格式: com.yfgame.gamename.newname</div>
+          <div>格式:com.gamename.newname</div>
         </template>
       </a-form-item>
-      <a-form-item label="小游戏分包参数" field="wxgamepro">
+      <a-form-item
+        label="分包参数"
+        field="wxgamepro"
+        v-if="formData.os == '3' || formData.os == '4'"
+      >
         <a-input
           v-model="formData.wxgamepro"
           placeholder="请输入小游戏分包参数"
         />
         <template #extra>
-          <div>格式: wxgamepro=PkgCBgAAoxxxx</div>
+          <div>格式:wxgamepro=PkgCBgAAoxxxx</div>
         </template>
       </a-form-item>
-      <a-form-item label="充值回调地址" field="cp_callback_url">
+
+      <a-form-item
+        label="iOS线上版本"
+        field="online_version"
+        v-if="formData.os == '2'"
+      >
         <a-input
-          v-model="formData.cp_callback_url"
-          placeholder="元宝发放地址,研发提供"
+          v-model="formData.online_version"
+          placeholder="请输入线上版本"
         />
+        <template #extra>
+          <div>iOS包内传参大于该版本则接口会返回审核服</div>
+        </template>
       </a-form-item>
-      <a-form-item label="线上版本" field="online_version">
+      <a-form-item label="充值回调" field="cp_callback_url">
         <a-input
-          v-model="formData.online_version"
-          placeholder="请输入线上版本(大于该版本返回审核服)"
+          v-model="formData.cp_callback_url"
+          placeholder="研发发货地址提供"
         />
       </a-form-item>
+      <a-form-item
+        label="研发登录地址"
+        field="cp_h5_url"
+        v-if="formData.os == '5'"
+      >
+        <a-input v-model="formData.cp_h5_url" placeholder="研发H5登录地址" />
+        <template #extra>
+          <div>H5或iOS-H5壳包必填</div>
+        </template>
+      </a-form-item>
       <a-form-item label="状态" field="status">
         <sa-switch v-model="formData.status" />
       </a-form-item>
-      <a-form-item label="排序" field="sort">
+      <!-- <a-form-item label="排序" field="sort">
         <a-input v-model="formData.sort" placeholder="请输入排序" />
       </a-form-item>
       <a-form-item label="描述" field="remark">
         <a-input v-model="formData.remark" placeholder="请输入描述" />
-      </a-form-item>
+      </a-form-item> -->
     </a-form>
     <!-- 表单信息 end -->
   </component>
@@ -116,8 +143,8 @@
 import { ref, reactive, computed } from "vue";
 import tool from "@/utils/tool";
 import { Message, Modal } from "@arco-design/web-vue";
-import api from "../../api/center/game";
-import centerCommonApi from "../../api/center/common";
+import api from "../../api/game";
+import centerCommonApi from "../../api/common";
 
 const emit = defineEmits(["success"]);
 // 引用定义
@@ -141,7 +168,7 @@ const initialFormData = {
   cp_h5_url: "",
   divide: "50",
   ios_divide: "50",
-  main_game_id: null,
+  main_game_id: "",
   cp_callback_type: 0,
   wxgamepro: "",
   online_version: "",
@@ -150,6 +177,7 @@ const initialFormData = {
   remark: "",
   package_name: "",
   cp_callback_url: "",
+  realname_switch: 2,
 };
 
 // 表单信息
@@ -160,10 +188,9 @@ const rules = {
   main_id: [{ required: true, message: "主包归属必需填写" }],
   name: [{ required: true, message: "游戏名称必需填写" }],
   os: [{ required: true, message: "平台必需选择" }],
-  package_name: [{ required: true, message: "包名必需填写" }],
   divide: [{ required: true, message: "分成比例必需填写" }],
   cp_callback_type: [{ required: true, message: "游戏发货规则必需选择" }],
-  online_version: [{ required: true, message: "线上版本必需填写" }],
+  realname_switch: [{ required: true, message: "游戏实名必需选择" }],
 };
 
 // 打开弹框
@@ -191,7 +218,15 @@ const getMainGameOptionsList = async () => {
 // 获取子游戏列表
 const getGameOptionsList = async () => {
   const { data } = await centerCommonApi.getGameOptionsApi();
-  gameOptions.value = data;
+  console.log(formData.name);
+  const newData = data.filter((item) => {
+    return item.label !== formData.name;
+  });
+  newData.unshift({
+    label: "默认生成独立key",
+    value: 0,
+  });
+  gameOptions.value = newData;
 };
 
 // 设置数据
@@ -208,9 +243,13 @@ const submit = async (done) => {
   const validate = await formRef.value?.validate();
   if (!validate) {
     loading.value = true;
-    let data = { ...formData };
+    let data = {
+      ...formData,
+      realname_switch: Number(formData.realname_switch),
+    };
+
     let result = {};
-    if (mode.value === "add") {
+    if (mode.value == "add") {
       // 添加数据
       data.id = undefined;
       result = await api.save(data);
@@ -218,7 +257,7 @@ const submit = async (done) => {
       // 修改数据
       result = await api.update(data.id, data);
     }
-    if (result.code === 200) {
+    if (result.code == 200) {
       Message.success("操作成功");
       emit("success");
       done(true);
@@ -231,6 +270,16 @@ const submit = async (done) => {
   done(false);
 };
 
+// handleMainGameChange
+const handleMainGameChange = (value) => {
+  console.log(value);
+  if (value == "") {
+    formData.cp_callback_type = "0";
+  } else {
+    formData.cp_callback_type = "1";
+  }
+};
+
 // 关闭弹窗
 const close = () => (visible.value = false);
 

+ 16 - 8
src/views/v1/center/game/index.vue

@@ -74,8 +74,8 @@ import { onMounted, ref, reactive } from "vue";
 import { Message } from "@arco-design/web-vue";
 import EditForm from "./edit.vue";
 import CpInfo from "./cp-info.vue";
-import api from "../../api/center/game";
-import apiCommon from "../../api/center/common";
+import api from "../../api/game";
+import apiCommon from "../../api/common";
 
 // 引用定义
 const crudRef = ref();
@@ -96,7 +96,7 @@ const searchForm = ref({
 // SaTable 基础配置
 const options = reactive({
   api: api.getPageList,
-  rowSelection: { showCheckedAll: true },
+  rowSelection: { showCheckedAll: false },
   operationColumnWidth: 280,
   add: {
     show: true,
@@ -115,7 +115,7 @@ const options = reactive({
     },
   },
   delete: {
-    show: true,
+    show: false,
     auth: ["/v1/center/Game/destroy"],
     func: async (params) => {
       const resp = await api.destroy(params);
@@ -129,8 +129,8 @@ const options = reactive({
 
 // SaTable 列配置
 const columns = reactive([
-  { title: "主包归属", dataIndex: "main_game_name", width: 130 },
   { title: "游戏名称", dataIndex: "name", width: 130 },
+  // { title: "主包归属", dataIndex: "main_game_name", width: 130 },
   { title: "包名", dataIndex: "package_name", width: 130 },
   {
     title: "平台",
@@ -141,10 +141,16 @@ const columns = reactive([
   },
 
   { title: "状态", dataIndex: "status", width: 80 },
-
+  {
+    title: "实名",
+    dataIndex: "realname_switch",
+    width: 80,
+    type: "dict",
+    dict: "realname_switch",
+  },
   { title: "充值回调地址", dataIndex: "cp_callback_url", width: 180 },
   { title: "分成比例", dataIndex: "divide", width: 120 },
-  { title: "创建时间", dataIndex: "create_time", width: 180 },
+  // { title: "创建时间", dataIndex: "create_time", width: 180 },
   { title: "修改时间", dataIndex: "update_time", width: 180 },
 ]);
 
@@ -177,13 +183,15 @@ const refresh = async () => {
 
 // 查看CP对接信息
 const checkCpInfo = async (record) => {
-  let { appkey, login_key, pay_key, name, id } = record;
+  let { appkey, login_key, pay_key, name, id, os } = record;
   let cp_info = {
     name: name,
     appid: id,
     appkey: appkey,
     login_key: login_key,
     pay_key: pay_key,
+    os: os,
+    channel_h5_url: `https://pf.game.com/game/login?appid=${id}`,
   };
   cpInfoRef.value?.open();
   cpInfoRef.value?.setFormData(cp_info);

+ 2 - 2
src/views/v1/center/gameMain/edit.vue

@@ -40,8 +40,8 @@
 import { ref, reactive, computed } from "vue";
 import tool from "@/utils/tool";
 import { Message, Modal } from "@arco-design/web-vue";
-import api from "../../api/center/gameMain";
-import centerCommonApi from "@/views/v1/api/center/common";
+import api from "../../api/gameMain";
+import centerCommonApi from "@/views/v1/api/common";
 
 const emit = defineEmits(["success"]);
 // 引用定义

+ 1 - 1
src/views/v1/center/gameMain/index.vue

@@ -36,7 +36,7 @@
 import { onMounted, ref, reactive } from "vue";
 import { Message } from "@arco-design/web-vue";
 import EditForm from "./edit.vue";
-import api from "../../api/center/gameMain";
+import api from "../../api/gameMain";
 
 // 引用定义
 const crudRef = ref();

+ 151 - 0
src/views/v1/center/iosPayWay/edit.vue

@@ -0,0 +1,151 @@
+<template>
+  <component
+    is="a-modal"
+    :width="tool.getDevice() === 'mobile' ? '100%' : '600px'"
+    v-model:visible="visible"
+    :title="title"
+    :mask-closable="false"
+    :ok-loading="loading"
+    @cancel="close"
+    @before-ok="submit"
+  >
+    <!-- 表单信息 start -->
+    <a-form
+      ref="formRef"
+      :model="formData"
+      :rules="rules"
+      :auto-label-width="true"
+    >
+      <a-form-item label="开启时间" field="pay_stime">
+        <a-time-picker
+          v-model="formData.pay_stime"
+          placeholder="请选择开启时间"
+        />
+      </a-form-item>
+      <a-form-item label="结束时间" field="pay_etime">
+        <a-time-picker
+          v-model="formData.pay_etime"
+          placeholder="请选择结束时间"
+        />
+      </a-form-item>
+      <a-form-item label="充值金额" field="pay_money">
+        <a-input v-model="formData.pay_money" placeholder="请输入充值金额" />
+      </a-form-item>
+      <a-form-item label="充值次数" field="pay_num">
+        <a-input v-model="formData.pay_num" placeholder="请输入充值次数" />
+      </a-form-item>
+      <a-form-item label="注册天数" field="reg_day">
+        <a-input v-model="formData.reg_day" placeholder="请输入注册天数" />
+      </a-form-item>
+      <a-form-item label="屏蔽地区" field="city">
+        <a-input v-model="formData.city" placeholder="请输入屏蔽地区" />
+      </a-form-item>
+      <a-form-item label="苹果支付" field="apple_pay">
+        <sa-switch v-model="formData.apple_pay" />
+      </a-form-item>
+      <a-form-item label="充值渠道开关" field="pay_way">
+        <sa-radio v-model="formData.pay_way" dict="open_close" />
+      </a-form-item>
+    </a-form>
+    <!-- 表单信息 end -->
+  </component>
+</template>
+
+<script setup>
+import { ref, reactive, computed } from "vue";
+import tool from "@/utils/tool";
+import { Message, Modal } from "@arco-design/web-vue";
+import api from "../../api/iosPayWay";
+
+const emit = defineEmits(["success"]);
+// 引用定义
+const visible = ref(false);
+const loading = ref(false);
+const formRef = ref();
+const mode = ref("");
+
+let title = computed(() => {
+  return "ios切支付" + (mode.value == "add" ? "-新增" : "-编辑");
+});
+
+// 表单初始值
+const initialFormData = {
+  id: null,
+  pay_stime: "",
+  pay_etime: "",
+  pay_money: 45,
+  pay_num: 2,
+  reg_day: 1,
+  city: "",
+  apple_pay: 1,
+  pay_way: "0",
+};
+
+// 表单信息
+const formData = reactive({ ...initialFormData });
+
+// 验证规则
+const rules = {
+  game_id: [{ required: true, message: "游戏名称必需填写" }],
+  pay_money: [{ required: true, message: "充值金额必需填写" }],
+  pay_num: [{ required: true, message: "充值次数必需填写" }],
+  reg_day: [{ required: true, message: "注册天数必需填写" }],
+  apple_pay: [{ required: true, message: "苹果支付必需填写" }],
+  pay_way: [{ required: true, message: "充值渠道开关必需填写" }],
+};
+
+// 打开弹框
+const open = async (type = "add") => {
+  mode.value = type;
+  // 重置表单数据
+  Object.assign(formData, initialFormData);
+  formRef.value.clearValidate();
+  visible.value = true;
+  await initPage();
+};
+
+// 初始化页面数据
+const initPage = async () => {};
+
+// 设置数据
+const setFormData = async (data) => {
+  for (const key in formData) {
+    if (data[key] != null && data[key] != undefined) {
+      formData[key] = data[key];
+    }
+  }
+};
+
+// 数据保存
+const submit = async (done) => {
+  const validate = await formRef.value?.validate();
+  if (!validate) {
+    loading.value = true;
+    let data = { ...formData };
+    let result = {};
+    if (mode.value === "add") {
+      // 添加数据
+      data.id = undefined;
+      result = await api.save(data);
+    } else {
+      // 修改数据
+      result = await api.update(data.id, data);
+    }
+    if (result.code === 200) {
+      Message.success("操作成功");
+      emit("success");
+      done(true);
+    }
+    // 防止连续点击提交
+    setTimeout(() => {
+      loading.value = false;
+    }, 500);
+  }
+  done(false);
+};
+
+// 关闭弹窗
+const close = () => (visible.value = false);
+
+defineExpose({ open, setFormData });
+</script>

+ 97 - 0
src/views/v1/center/iosPayWay/index.vue

@@ -0,0 +1,97 @@
+<template>
+  <div class="ma-content-block">
+    <sa-table
+      ref="crudRef"
+      :options="options"
+      :columns="columns"
+      :searchForm="searchForm"
+    >
+      <!-- 搜索区 tableSearch -->
+      <template #tableSearch> </template>
+
+      <!-- Table 自定义渲染 -->
+    </sa-table>
+
+    <!-- 编辑表单 -->
+    <edit-form ref="editRef" @success="refresh" />
+  </div>
+</template>
+
+<script setup>
+import { onMounted, ref, reactive } from "vue";
+import { Message } from "@arco-design/web-vue";
+import EditForm from "./edit.vue";
+import api from "../../api/iosPayWay";
+
+// 引用定义
+const crudRef = ref();
+const editRef = ref();
+const viewRef = ref();
+
+// 搜索表单
+const searchForm = ref({});
+
+// SaTable 基础配置
+const options = reactive({
+  api: api.getPageList,
+  rowSelection: { showCheckedAll: true },
+  add: {
+    show: true,
+    auth: ["/v1/center/IosPayWay/save"],
+    func: async () => {
+      editRef.value?.open();
+    },
+  },
+  edit: {
+    show: true,
+    auth: ["/v1/center/IosPayWay/update"],
+    func: async (record) => {
+      editRef.value?.open("edit");
+      editRef.value?.setFormData(record);
+    },
+  },
+  delete: {
+    show: true,
+    auth: ["/v1/center/IosPayWay/destroy"],
+    func: async (params) => {
+      const resp = await api.destroy(params);
+      if (resp.code === 200) {
+        Message.success(`删除成功!`);
+        crudRef.value?.refresh();
+      }
+    },
+  },
+});
+
+// SaTable 列配置
+const columns = reactive([
+  { title: "开启时间", dataIndex: "pay_stime", width: 180 },
+  { title: "结束时间", dataIndex: "pay_etime", width: 180 },
+  { title: "充值金额", dataIndex: "pay_money", width: 180 },
+  { title: "充值次数", dataIndex: "pay_num", width: 180 },
+  { title: "注册天数", dataIndex: "reg_day", width: 180 },
+  { title: "屏蔽地区", dataIndex: "city", width: 180 },
+  { title: "苹果支付", dataIndex: "apple_pay", width: 180 },
+  {
+    title: "充值渠道开关",
+    dataIndex: "pay_way",
+    type: "dict",
+    dict: "open_close",
+    width: 120,
+  },
+]);
+
+// 页面数据初始化
+const initPage = async () => {};
+
+// SaTable 数据请求
+const refresh = async () => {
+  crudRef.value?.refresh();
+};
+
+// 页面加载完成执行
+onMounted(async () => {
+  initPage();
+  refresh();
+});
+</script>

+ 139 - 0
src/views/v1/center/qxSwitch/edit.vue

@@ -0,0 +1,139 @@
+<template>
+  <component
+    is="a-modal"
+    :width="tool.getDevice() === 'mobile' ? '100%' : '600px'"
+    v-model:visible="visible"
+    :title="title"
+    :mask-closable="false"
+    :ok-loading="loading"
+    @cancel="close"
+    @before-ok="submit"
+  >
+    <!-- 表单信息 start -->
+    <a-form
+      ref="formRef"
+      :model="formData"
+      :rules="rules"
+      :auto-label-width="true"
+    >
+      <a-form-item label="包名" field="package_name">
+        <a-input v-model="formData.package_name" placeholder="请输入包名" />
+      </a-form-item>
+      <a-form-item label="咨询允许获得" field="qx">
+        <sa-switch
+          v-model="formData.qx"
+          checkedText="开启"
+          uncheckedText="关闭"
+        />
+      </a-form-item>
+      <a-form-item label="隐私弹窗" field="ystc">
+        <sa-switch
+          v-model="formData.ystc"
+          checkedText="开启"
+          uncheckedText="关闭"
+        />
+      </a-form-item>
+      <a-form-item label="登录框同意勾选文案" field="init">
+        <sa-switch
+          v-model="formData.init"
+          checkedText="开启"
+          uncheckedText="关闭"
+        />
+      </a-form-item>
+    </a-form>
+    <!-- 表单信息 end -->
+  </component>
+</template>
+
+<script setup>
+import { ref, reactive, computed } from "vue";
+import tool from "@/utils/tool";
+import { Message, Modal } from "@arco-design/web-vue";
+import api from "../../api/qxSwitch";
+
+const emit = defineEmits(["success"]);
+// 引用定义
+const visible = ref(false);
+const loading = ref(false);
+const formRef = ref();
+const mode = ref("");
+
+let title = computed(() => {
+  return "权限开关" + (mode.value == "add" ? "-新增" : "-编辑");
+});
+
+// 表单初始值
+const initialFormData = {
+  id: null,
+  package_name: "",
+  qx: 1,
+  ystc: 1,
+  init: 1,
+};
+
+// 表单信息
+const formData = reactive({ ...initialFormData });
+
+// 验证规则
+const rules = {
+  package_name: [{ required: true, message: "包名必需填写" }],
+  qx: [{ required: true, message: "咨询允许获得必需填写" }],
+  ystc: [{ required: true, message: "隐私弹窗必需填写" }],
+  init: [{ required: true, message: "登录框同意勾选文案必需填写" }],
+};
+
+// 打开弹框
+const open = async (type = "add") => {
+  mode.value = type;
+  // 重置表单数据
+  Object.assign(formData, initialFormData);
+  formRef.value.clearValidate();
+  visible.value = true;
+  await initPage();
+};
+
+// 初始化页面数据
+const initPage = async () => {};
+
+// 设置数据
+const setFormData = async (data) => {
+  for (const key in formData) {
+    if (data[key] != null && data[key] != undefined) {
+      formData[key] = data[key];
+    }
+  }
+};
+
+// 数据保存
+const submit = async (done) => {
+  const validate = await formRef.value?.validate();
+  if (!validate) {
+    loading.value = true;
+    let data = { ...formData };
+    let result = {};
+    if (mode.value === "add") {
+      // 添加数据
+      data.id = undefined;
+      result = await api.save(data);
+    } else {
+      // 修改数据
+      result = await api.update(data.id, data);
+    }
+    if (result.code === 200) {
+      Message.success("操作成功");
+      emit("success");
+      done(true);
+    }
+    // 防止连续点击提交
+    setTimeout(() => {
+      loading.value = false;
+    }, 500);
+  }
+  done(false);
+};
+
+// 关闭弹窗
+const close = () => (visible.value = false);
+
+defineExpose({ open, setFormData });
+</script>

+ 135 - 0
src/views/v1/center/qxSwitch/index.vue

@@ -0,0 +1,135 @@
+<template>
+  <div class="ma-content-block">
+    <sa-table
+      ref="crudRef"
+      :options="options"
+      :columns="columns"
+      :searchForm="searchForm"
+    >
+      <!-- 搜索区 tableSearch -->
+      <template #tableSearch>
+        <a-col :sm="8" :xs="24">
+          <a-form-item label="包名" field="package_name">
+            <a-input
+              v-model="searchForm.package_name"
+              placeholder="请输入包名"
+              allow-clear
+            />
+          </a-form-item>
+        </a-col>
+      </template>
+
+      <!-- Table 自定义渲染 -->
+      <template #qx="{ record }">
+        <sa-switch
+          checkedText="开启"
+          uncheckedText="关闭"
+          v-model="record.qx"
+          @change="changeStatus($event, record, 'qx')"
+        />
+      </template>
+      <template #ystc="{ record }">
+        <sa-switch
+          checkedText="开启"
+          uncheckedText="关闭"
+          v-model="record.ystc"
+          @change="changeStatus($event, record, 'ystc')"
+        />
+      </template>
+      <template #init="{ record }">
+        <sa-switch
+          checkedText="开启"
+          uncheckedText="关闭"
+          v-model="record.init"
+          @change="changeStatus($event, record, 'init')"
+        />
+      </template>
+    </sa-table>
+
+    <!-- 编辑表单 -->
+    <edit-form ref="editRef" @success="refresh" />
+  </div>
+</template>
+
+<script setup>
+import { onMounted, ref, reactive } from "vue";
+import { Message } from "@arco-design/web-vue";
+import EditForm from "./edit.vue";
+import api from "../../api/qxSwitch";
+
+// 引用定义
+const crudRef = ref();
+const editRef = ref();
+const viewRef = ref();
+
+// 搜索表单
+const searchForm = ref({
+  package_name: "",
+});
+
+// 修改状态
+const changeStatus = async (status, record, field) => {
+  const response = await api.update(record.id, {
+    ...record,
+    [field]: status,
+  });
+  if (response.code === 200) {
+    Message.success(response.message);
+    crudRef.value.refresh();
+  }
+};
+
+// SaTable 基础配置
+const options = reactive({
+  api: api.getPageList,
+  rowSelection: { showCheckedAll: true },
+  add: {
+    show: true,
+    auth: ["/v1/center/QxSwitch/save"],
+    func: async () => {
+      editRef.value?.open();
+    },
+  },
+  edit: {
+    show: true,
+    auth: ["/v1/center/QxSwitch/update"],
+    func: async (record) => {
+      editRef.value?.open("edit");
+      editRef.value?.setFormData(record);
+    },
+  },
+  delete: {
+    show: true,
+    auth: ["/v1/center/QxSwitch/destroy"],
+    func: async (params) => {
+      const resp = await api.destroy(params);
+      if (resp.code === 200) {
+        Message.success(`删除成功!`);
+        crudRef.value?.refresh();
+      }
+    },
+  },
+});
+
+// SaTable 列配置
+const columns = reactive([
+  { title: "包名", dataIndex: "package_name", width: 180 },
+  { title: "咨询允许获得", dataIndex: "qx", width: 180 },
+  { title: "隐私弹窗", dataIndex: "ystc", width: 180 },
+  { title: "登录框同意勾选文案", dataIndex: "init", width: 180 },
+]);
+
+// 页面数据初始化
+const initPage = async () => {};
+
+// SaTable 数据请求
+const refresh = async () => {
+  crudRef.value?.refresh();
+};
+
+// 页面加载完成执行
+onMounted(async () => {
+  initPage();
+  refresh();
+});
+</script>