GGitee1
d84c6c56创建于 3月25日历史提交
<script setup lang="ts">
import { h, ref } from "vue";
import {
  type FieldValues,
  PlusForm,
  PlusFormGroupRow,
} from "plus-pro-components";
import markdown from "markdown.vue";
import customMD from "customMD.vue";
import mdSuffix from "mdSuffix.vue";
import filterLog from "filterLog.vue";
import btnSuffix from "btnSuffix.vue";
import token from "token.vue";
import addDialog from "@addDialog";
import message from "@message";
import { clone } from "@pureadmin/utils";

defineOptions({
  name: "setting",
});

const props = defineProps({
  // method, url, param, axiosConfig
  request: Function,
});

// 表单绑定值
const state = ref({
  permission: "",
  toQRCode: "",
  toCallback: false,
  toBotUpload: false,
  hideGuildRecall: false,
  toQQUin: false,
  toImg: false,
  sendButton: false,
  callStats: false,
  userStats: false,
  simplifiedSdkLog: false,
  markdownImgScale: false,
  sep: "",
  bot: {
    sandbox: false,
    maxRetry: 0,
    timeout: 0,
  },
  dauDB: "level",
  markdown: {},
  customMD: {},
  mdSuffix: {},
  filterLog: {},
  btnSuffix: {},
  token: [],
});

const getData = () => {
  props
    .request("post", `/get-setting-data`)
    .then((res) => res.data)
    .then((data) => {
      for (const key in data) {
        state.value[key] = data[key];
      }
      state.value.token = [];
      for (const i of data.token as string[]) {
        const [uin, appid, token, appSecret, isGroup, isPrivate] = i.split(":");
        state.value.token.push({
          uin,
          appid,
          token,
          appSecret,
          isGroup: Number(isGroup),
          isPrivate: Number(isPrivate),
        });
      }
      for (const key in state.value.btnSuffix) {
        state.value.btnSuffix[key].values.forEach((i: any) => {
          for (const k of ["input", "callback", "link"]) {
            if (i[k]) {
              i.type = k;
              i.data = i[k];
              break;
            }
          }
        });
      }
    });
};

getData();

// 表单校验规则
const rules = {
  permission: [
    {
      required: true,
      message: "请选择权限",
    },
  ],
  dauDB: [
    {
      required: true,
      message: "请选择dau数据库",
    },
  ],
};

const fieldProps = {
  activeValue: true,
  inactiveValue: false,
};

const group: PlusFormGroupRow[] = [
  {
    title: "基础设置",
    columns: [
      {
        label: "权限",
        prop: "permission",
        valueType: "radio",
        options: [
          {
            label: "master",
            value: "master",
          },
          {
            label: "owner",
            value: "owner",
          },
          {
            label: "admin",
            value: "admin",
          },
          {
            label: "all",
            value: "all",
          },
        ],
        colProps: {
          span: 12,
          xs: 23,
        },
      },
      {
        label: "dau数据库",
        prop: "dauDB",
        valueType: "radio",
        tooltip: "重启后生效",
        options: [
          {
            label: "level",
            value: "level",
          },
          {
            label: "redis",
            value: "redis",
          },
          {
            label: "关闭",
            value: false,
          },
        ],
        colProps: {
          span: 12,
          xs: 23,
        },
      },
      {
        label: "md图片缩放",
        prop: "markdownImgScale",
        valueType: "input-number",
        fieldProps: {
          precision: 1,
          step: 0.1,
        },
        colProps: {
          span: 12,
          xs: 23,
        },
      },
      {
        label: "ID分隔符",
        prop: "sep",
        valueType: "input",
        tooltip: "重启后生效",
        colProps: {
          span: 11,
          xs: 23,
        },
        fieldProps: {
          placeholder: "可为空",
        },
      },
      {
        label: "链接正则",
        prop: "toQRCode",
        valueType: "input",
        tooltip: "发送url需要备案,匹配url转换二维码",
        fieldProps: {
          placeholder: "请输入正则或为空关闭",
        },
        colProps: {
          span: 23,
          xs: 23,
        },
      },
    ],
  },
  {
    title: "扩展功能",
    columns: [
      {
        label: "按钮回调",
        prop: "toCallback",
        valueType: "switch",
        fieldProps,
        colProps: {
          span: 6,
          xs: 12,
        },
      },
      {
        label: "上传图片",
        prop: "toBotUpload",
        valueType: "switch",
        tooltip: "使用其他Bot上传图链",
        fieldProps,
        colProps: {
          span: 6,
          xs: 12,
        },
      },
      {
        label: "隐藏频道撤回",
        prop: "hideGuildRecall",
        valueType: "switch",
        fieldProps,
        colProps: {
          span: 6,
          xs: 12,
        },
      },
      {
        label: "真实QQ",
        prop: "toQQUin",
        valueType: "switch",
        tooltip: "配合ws-plugin的绑定",
        fieldProps,
        colProps: {
          span: 6,
          xs: 12,
        },
      },
      {
        label: "转发消息转图",
        prop: "toImg",
        valueType: "switch",
        fieldProps,
        colProps: {
          span: 6,
          xs: 12,
        },
      },
      {
        label: "发送按钮",
        prop: "sendButton",
        valueType: "switch",
        tooltip: "没有自定义按钮权限请关闭此项",
        fieldProps,
        colProps: {
          span: 6,
          xs: 12,
        },
      },
      {
        label: "调用统计",
        prop: "callStats",
        valueType: "switch",
        fieldProps,
        colProps: {
          span: 6,
          xs: 12,
        },
      },
      {
        label: "用户统计",
        prop: "userStats",
        valueType: "switch",
        fieldProps,
        colProps: {
          span: 6,
          xs: 12,
        },
      },
    ],
  },
  {
    title: "高阶功能",
    columns: [
      {
        label: "markdown",
        prop: "markdown",
        tooltip: "是否开启全局md",
        colProps: {
          span: 11,
          xs: 23,
        },
      },
      {
        label: "md模版",
        prop: "customMD",
        colProps: {
          span: 12,
          xs: 23,
        },
      },
      {
        label: "md附加值",
        prop: "mdSuffix",
        colProps: {
          span: 11,
          xs: 23,
        },
      },
      {
        label: "按钮附加值",
        prop: "btnSuffix",
        colProps: {
          span: 12,
          xs: 23,
        },
      },
    ],
  },
  {
    title: "日志相关",
    columns: [
      {
        label: "缩短日志",
        prop: "simplifiedSdkLog",
        valueType: "switch",
        fieldProps,
        tooltip: "缩短sdk的日志",
        width: 500,
        colProps: {
          span: 6,
        },
      },
      {
        label: "过滤日志",
        prop: "filterLog",
        colProps: {
          span: 18,
          xs: 23,
        },
      },
    ],
  },
  {
    title: "sdk相关",
    columns: [
      {
        label: "沙盒模式",
        prop: "bot.sandbox",
        valueType: "switch",
        tooltip: "重启后生效",
        fieldProps,
        colProps: {
          span: 6,
          xs: 23,
        },
      },
      {
        label: "最大重连次数",
        prop: "bot.maxRetry",
        valueType: "input-number",
        tooltip: "为0则无限重连",
        colProps: {
          span: 8,
          xs: 23,
        },
      },
      {
        label: "请求超时时间",
        prop: "bot.timeout",
        valueType: "input-number",
        tooltip: "重启后生效",
        colProps: {
          span: 8,
          xs: 23,
        },
      },
    ],
  },
  {
    title: "核心功能",
    columns: [
      {
        label: "token",
        prop: "token",
        tooltip: "重启后生效",
        colProps: {
          span: 23,
          xs: 23,
        },
      },
    ],
  },
];

const submitLoading = ref(false);
const handleSubmit = (values: FieldValues) => {
  submitLoading.value = true;
  const data = clone(values, true) as any;
  data.token = data.token.map(
    (i) =>
      `${i.uin}:${i.appid}:${i.token}:${i.appSecret}:${i.isGroup}:${i.isPrivate}`
  );
  for (const key in data.btnSuffix) {
    data.btnSuffix[key].values.forEach((i: any) => {
      for (const type of ["input", "callback", "link"]) {
        if (i.type === type) {
          i[type] = i.data;
          delete i.type;
          delete i.data;
          for (const val in i) {
            const v = i[val];
            if ((Array.isArray(v) && !v.length) || !v) {
              delete i[val];
            }
          }
          if (!i.show?.type || !i.show.data) {
            delete i.show;
          }
          break;
        }
      }
    });
  }
  props
    .request("post", `/set-setting-data`, {
      data: { data },
    })
    .then((res) => {
      if (res.success) {
        message("保存成功~ Ciallo~(∠・ω< )⌒☆", {
          customClass: "el",
          type: "success",
        });
      } else {
        message("保存失败: " + res.message, {
          customClass: "el",
          type: "error",
        });
      }
      submitLoading.value = false;
    });
};
const handleSubmitError = (err: any) => {};

const closeTag = (tag: string) => {
  const [key, value] = tag.split(":");
  delete state.value[key][value];
};

const closeTokenTag = (tag: string) => {
  const keys = state.value.token as Array<TokenFormProps["formInline"]>;
  const index = keys.findIndex((item) => item.uin == tag);
  if (index > -1) {
    keys.splice(index, 1);
  }
};

const initData = {
  markdown: {
    uin: "",
    id: "",
  },
  customMD: {
    uin: "",
    id: "",
    keys: [],
  },
  mdSuffix: {
    uin: "",
    val: [],
  },
  btnSuffix: {
    uin: "",
    position: 1,
    values: [],
  },
  filterLog: {
    uin: "",
    val: [],
  },
  token: {
    uin: "",
    token: "",
    appid: "",
    appSecret: "",
    isGroup: 0,
    isPrivate: 0,
  },
};

const getFormInline = (key: string | null, name: string) => {
  const formInline = clone(initData[name], true);
  if (key && state.value[name][key]) {
    switch (name) {
      case "markdown":
        formInline.uin = key;
        formInline.id = state.value.markdown[key];
        break;
      case "customMD":
        formInline.uin = key;
        formInline.id = state.value.customMD[key].custom_template_id;
        formInline.keys = state.value.customMD[key].keys;
        break;
      case "mdSuffix":
        formInline.uin = key;
        formInline.val = state.value.mdSuffix[key];
        break;
      case "btnSuffix":
        formInline.position = state.value.btnSuffix[key].position;
        formInline.values = state.value.btnSuffix[key].values;
        formInline.uin = key;
        break;
      case "filterLog":
        formInline.uin = key;
        formInline.val = state.value.filterLog[key];
        break;
      case "token":
        formInline.uin = state.value.token[key].uin;
        formInline.token = state.value.token[key].token;
        formInline.appid = state.value.token[key].appid;
        formInline.appSecret = state.value.token[key].appSecret;
        formInline.isGroup = state.value.token[key].isGroup;
        formInline.isPrivate = state.value.token[key].isPrivate;
        break;
      default:
        break;
    }
  }
  return formInline;
};

const closeCallBack = ({ options, args }, key: string | null, name: string) => {
  const { formInline } = options.props;
  if (args?.command === "sure") {
    if (name === "token") {
      key = key ?? "-1";
    } else {
      if (!key || key === formInline.uin) {
        key = formInline.uin;
      } else {
        delete state.value[name][key];
        key = formInline.uin;
      }
    }
    switch (name) {
      case "markdown":
        state.value.markdown[key] = formInline.id;
        break;
      case "customMD":
        state.value.customMD[key] = {
          custom_template_id: formInline.id,
          keys: formInline.keys,
        };
        break;
      case "mdSuffix":
        state.value.mdSuffix[key] = formInline.val;
        break;
      case "btnSuffix":
        state.value.btnSuffix[key] = {
          position: formInline.position,
          values: formInline.values,
        };
        break;
      case "filterLog":
        state.value.filterLog[key] = formInline.val;
        break;
      case "token":
        const token = state.value.token as Array<TokenFormProps["formInline"]>;
        if (Number(key) > -1) {
          token[key] = formInline;
        } else {
          token.push(formInline);
        }
        break;
      default:
        break;
    }
  }
};

const formRef = ref();
const showDialog = (title: string, key: string | null, content: any) => {
  addDialog({
    width:
      window.innerWidth < 992
        ? "90%"
        : window.innerWidth <= 1200
          ? "50%"
          : "25%",
    title,
    contentRenderer: () => h(content, { ref: formRef }),
    props: {
      formInline: getFormInline(key, content.__name),
    },
    closeCallBack: ({ options, args }) =>
      closeCallBack({ options, args }, key, content.__name),
    beforeSure: (done, { options, index }) => {
      const FormRef = formRef.value.getRef();
      FormRef.validate((valid: boolean) => {
        if (valid) {
          done();
        }
      });
    },
    draggable: true,
  });
};
</script>

<template>
  <div>
    <el-row justify="center">
      <el-col :lg="14" xs="24">
        <PlusForm
          v-model="state"
          :rules="rules"
          :group="group"
          label-position="right"
          resetText="重置"
          submitText="保存"
          footerAlign="center"
          labelWidth="120px"
          :submitLoading="submitLoading"
          @submit="handleSubmit"
          @submit-error="handleSubmitError"
          @reset="getData"
        >
          <template #plus-field-markdown>
            <el-tag
              v-for="(val, key) in state.markdown"
              :key="key"
              class="mx-1 cursor-pointer mt-1"
              style="margin: 1px 1px 0 1px"
              :closable="key !== 'template'"
              @close="closeTag('markdown:' + key)"
              @click="showDialog('修改Markdown模版', String(key), markdown)"
            >
              {{ key }}
            </el-tag>
            <el-button
              class="button-new-tag ml-1"
              size="small"
              @click="showDialog('增加Markdown模版', null, markdown)"
            >
              新增
            </el-button>
          </template>
          <template #plus-field-customMD>
            <el-tag
              v-for="(val, key) in state.customMD"
              :key="key"
              class="mx-1 cursor-pointer mt-1"
              closable
              @close="closeTag('customMD:' + key)"
              @click="showDialog('修改自定义Markdown模版', key, customMD)"
            >
              {{ key }}
            </el-tag>
            <el-button
              class="button-new-tag ml-1"
              size="small"
              @click="showDialog('增加自定义Markdown模版', null, customMD)"
            >
              新增
            </el-button>
          </template>
          <template #plus-field-mdSuffix>
            <el-tag
              v-for="(val, key) in state.mdSuffix"
              :key="key"
              class="mx-1 cursor-pointer mt-1"
              closable
              @close="closeTag('mdSuffix:' + key)"
              @click="showDialog('修改Markdown附加值', key, mdSuffix)"
            >
              {{ key }}
            </el-tag>
            <el-button
              class="button-new-tag ml-1"
              size="small"
              @click="showDialog('增加Markdown附加值', null, mdSuffix)"
            >
              新增
            </el-button>
          </template>
          <template #plus-field-btnSuffix>
            <el-tag
              v-for="(val, key) in state.btnSuffix"
              :key="key"
              class="mx-1 cursor-pointer mt-1"
              closable
              @close="closeTag('btnSuffix:' + key)"
              @click="showDialog('修改按钮附加值', key, btnSuffix)"
            >
              {{ key }}
            </el-tag>
            <el-button
              class="button-new-tag ml-1"
              size="small"
              @click="showDialog('增加按钮附加值', null, btnSuffix)"
            >
              新增
            </el-button>
          </template>
          <template #plus-field-filterLog>
            <el-tag
              v-for="(val, key) in state.filterLog"
              :key="key"
              class="mx-1 cursor-pointer mt-1"
              closable
              @close="closeTag('filterLog:' + key)"
              @click="showDialog('修改过滤日志', key, filterLog)"
            >
              {{ key }}
            </el-tag>
            <el-button
              class="button-new-tag ml-1"
              size="small"
              @click="showDialog('增加过滤日志', null, filterLog)"
            >
              新增
            </el-button>
          </template>
          <template #plus-field-token>
            <el-tag
              v-for="(val, index) in state.token"
              :key="val.uin"
              class="mx-1 cursor-pointer mt-1"
              closable
              @close="closeTokenTag(val.uin)"
              @click="showDialog('修改Token', String(index), token)"
            >
              {{ val.uin }}
            </el-tag>
            <el-button
              class="button-new-tag ml-1"
              size="small"
              @click="showDialog('增加Token', null, token)"
            >
              新增
            </el-button>
          </template>
        </PlusForm>
      </el-col>
    </el-row>
  </div>
</template>

<style scoped>
.cursor-pointer {
  cursor: pointer;
}

.mx-1 {
  margin-right: 0.25rem;
  margin-left: 0.25rem;
}

.mt-1 {
  margin-top: 0.25rem;
}

.ml-1 {
  margin-left: 0.25rem;
}
</style>