lcl 8 ماه پیش
والد
کامیت
f3c48ea58c

+ 14 - 43
src/components/Editor/index.vue

@@ -1,8 +1,8 @@
 <!--
  * @Author: Gui
  * @Date: 2023-03-01 19:20:44
- * @LastEditors: Please set LastEditors
- * @LastEditTime: 2023-06-12 10:39:51
+ * @LastEditors: guicheng 1625811865@qq.com
+ * @LastEditTime: 2024-06-20 15:03:36
  * @Description: kxs files
  * @filePath: 
 -->
@@ -12,14 +12,7 @@ import { Editor, Toolbar } from "@wangeditor/editor-for-vue";
 import { onBeforeUnmount, ref, shallowRef, onMounted, watch } from "vue";
 import Ossupload from "@/utils/OSSupload";
 
-const props = defineProps<{
-  titleText?: string;
-  editorContent: {
-    content: "";
-    title: "";
-    type: Object;
-  };
-}>();
+const props = defineProps<{}>();
 type Res = {
   url?: string;
   describe?: string;
@@ -30,12 +23,8 @@ const editorRef = shallowRef();
 
 // 内容 HTML
 const valueHtml = ref("");
-watch(props, res => {
-  valueHtml.value = res.editorContent.content;
-  valueTitle.value = res.editorContent.title;
-});
 // 模拟异步获取内容
-onMounted(() => {});
+onMounted(() => { });
 
 const toolbarConfig: any = { excludeKeys: "fullScreen" };
 const editorConfig = {
@@ -122,10 +111,8 @@ editorConfig.MENU_CONF["uploadVideo"] = {
     });
   }
 };
-const valueTitle = ref("");
 defineExpose({
-  valueHtml,
-  valueTitle
+  valueHtml
 });
 // const buttonclick = function () {
 //   const _source = editorRef.value.getText();
@@ -145,36 +132,17 @@ defineExpose({
 <template>
   <!-- <el-button type="primary" @click="buttonclick">转文字</el-button>
   <el-button type="primary" @click="buttonclick1">转代码</el-button> -->
-  <el-input
-    v-model="valueTitle"
-    placeholder="请输入标题"
-    size="large"
-    class="mb12"
-  >
-    <template #prepend>{{
-      props.titleText ? props.titleText : "标题"
-    }}</template>
-  </el-input>
   <div class="wangeditor">
-    <Toolbar
-      style="border-bottom: 1px solid #ccc"
-      :editor="editorRef"
-      :defaultConfig="toolbarConfig"
-      :mode="mode"
-    />
-    <Editor
-      style="height: 700px; overflow-y: hidden"
-      v-model="valueHtml"
-      :defaultConfig="editorConfig"
-      :mode="mode"
-      @onCreated="handleCreated"
-    />
+    <Toolbar style="border-bottom: 1px solid #ccc" :editor="editorRef" :defaultConfig="toolbarConfig" :mode="mode" />
+    <Editor style="height: 700px; overflow-y: hidden" v-model="valueHtml" :defaultConfig="editorConfig" :mode="mode"
+      @onCreated="handleCreated" />
   </div>
 </template>
 <style lang="css">
 .editor-content-view p,
 .editor-content-view li {
-  white-space: pre-wrap; /* 保留空格 */
+  white-space: pre-wrap;
+  /* 保留空格 */
 }
 
 .editor-content-view blockquote {
@@ -190,7 +158,8 @@ defineExpose({
   padding: 3px;
   border-radius: 3px;
 }
-.editor-content-view pre > code {
+
+.editor-content-view pre>code {
   display: block;
   padding: 10px;
 }
@@ -198,12 +167,14 @@ defineExpose({
 .editor-content-view table {
   border-collapse: collapse;
 }
+
 .editor-content-view td,
 .editor-content-view th {
   border: 1px solid #ccc;
   min-width: 50px;
   height: 20px;
 }
+
 .editor-content-view th {
   background-color: #f1f1f1;
 }

+ 186 - 0
src/components/UploadImg/index.vue

@@ -0,0 +1,186 @@
+<!--
+ * @Author: Gui
+ * @Date: 2023-05-12 11:36:28
+ * @LastEditors: guicheng 1625811865@qq.com
+ * @LastEditTime: 2024-06-20 16:14:29
+ * @Description: kxs files
+ * @filePath: 
+-->
+<template lang="pug">
+el-upload(
+ref="uploadRef"
+v-model:file-list="fileList"
+action="http://oss.kexiaoshuang.com"
+list-type="picture-card"
+:on-change="onChange"
+:auto-upload="false"
+:on-preview="handlePictureCardPreview"
+:on-remove="handleRemove"
+:limit="props.limit"
+)
+  IconifyIconOnline( icon="material-symbols:add-rounded" width="60px" height="60px" style="margin:0 auto;color:#999")
+  template(#tip)
+    .el-upload__tip.text-red 最多上传{{props.limit}}张图片
+el-dialog( v-model="dialogVisible" title="图片预览" width="80%" draggable :destroy-on-close="true")
+  div(class="flex justify-center align-middle" )
+    img.preview(w-full :src="dialogImageUrl" alt="Preview Image" style="width:100%;height:100%;")
+
+el-dialog(v-model="clipPhoto" title="裁剪图片" :destroy-on-close="true" draggable width="30vw")
+
+  ReCropper(
+    ref="refCropper"
+    class="w-[30vw] h-[30vh]"
+    :src="selectImg"
+    :options={aspectRatio:aspectRatio}
+  )
+  template( #footer="")
+    .flex
+      el-button( @click="clipPhoto = false") 取消 
+      el-button( type="primary" @click="confirmAdd") 确定
+
+</template>
+<script lang="ts" setup>
+import { getConfig } from "@/config";
+import { ref, nextTick, onMounted, watch } from "vue";
+import Ossupload from "@/utils/OSSupload";
+import type { UploadProps, UploadUserFile } from "element-plus";
+import { ElMessage } from "element-plus";
+import ReCropper from "@/components/ReCropper";
+
+type Res = {
+  uploadurl?: string; // 上传地址
+  url?: string; // 上传地址(+域名)
+};
+const props = defineProps({
+  limit: {
+    type: Number,
+    default: 1
+  },
+  cropper: {
+    type: Boolean,
+    default: false
+  },
+  callBack: {
+    type: Function,
+    default: () => { }
+  },
+  imgList: {
+    type: Object,
+    default: []
+  },
+
+});
+onMounted(() => {
+  console.log(props.imgList, 12312)
+  if (props.imgList && props.imgList.length > 0) {
+    props.imgList.forEach(item => {
+      fileList.value.push({ name: "1", url: item });
+      UrlList.value.push(item.split(getConfig().UploadUrl + '/')[1]);
+    })
+  }
+  console.log(fileList.value, 'fileList', UrlList.value)
+})
+// watch(
+//   () => props.imgList,
+//   newValue => {
+//     console.log(newValue)
+//     if (newValue) {
+//       initImg()
+//       newValue.forEach(item => {
+//         fileList.value.push({ name: "1", url: item });
+//         UrlList.value.push(item.split(getConfig().UploadUrl + '/')[1]);
+//       })
+//     } else {
+//       initImg()
+//     }
+//     console.log(fileList.value, 'fileList', UrlList.value)
+//   }
+// );
+const aspectRatio = ref(1);
+// 文件列表
+const fileList = ref<UploadUserFile[]>([]);
+// 上传路径列表
+const UrlList = ref<UploadUserFile[]>([]);
+// 图片上传、预览、裁剪
+const dialogImageUrl = ref("");
+// 是否预览
+const dialogVisible = ref(false);
+// 是否裁剪图片
+const clipPhoto = ref(false);
+// 裁剪的图片
+const selectImg = ref("");
+// 裁剪之后的图片
+const cropperImgName = ref("");
+const uploadRef = ref();
+const refCropper = ref();
+
+const onChange = (file: any) => {
+  if (
+    file.raw.type == "image/webp" ||
+    file.raw.type == "image/png" ||
+    file.raw.type == "image/jpeg"
+  ) {
+    if (file.status == "ready") {
+      // 裁剪
+      if (props.cropper) {
+        selectImg.value = file!.url;
+        cropperImgName.value = file.name;
+        clipPhoto.value = true;
+      } else {
+        // 直接上传,不需要裁剪
+        OssUp(file.raw);
+      }
+    }
+  } else {
+    ElMessage({
+      message: "仅支持png/jpg/webp 格式的图片文件",
+      type: "error"
+    });
+  }
+  nextTick(() => {
+    uploadRef.value.clearFiles(["ready", "uploading", "fail"]);
+  });
+};
+const handlePictureCardPreview: UploadProps["onPreview"] = uploadFile => {
+  dialogImageUrl.value = uploadFile.url!;
+  dialogVisible.value = true;
+};
+const handleRemove: UploadProps["onRemove"] = (uploadFile, uploadFiles) => {
+  fileList.value = uploadFiles;
+  // console.log(uploadFiles, '--删除', uploadFile)
+  let uploadFilesdata = []
+  uploadFiles.forEach((item: any) => {
+    uploadFilesdata.push(item.url.split(getConfig().UploadUrl + '/')[1])
+  })
+  UrlList.value = uploadFilesdata
+};
+const initImg = () => {
+
+  fileList.value = []
+  UrlList.value = []
+  // fileList.value.push({ name: cropperImgName.value, url: res.url });
+  // UrlList.value.push(res.uploadurl);
+
+}
+const confirmAdd = (): void => {
+  nextTick(() => {
+    refCropper.value.cropper.getCroppedCanvas().toBlob(blob => {
+      // upload to oss
+      const file = new File([blob], cropperImgName.value, {
+        type: "image/png"
+      });
+      OssUp(file);
+    }, "image/jpeg");
+    clipPhoto.value = false;
+  });
+};
+const OssUp = file => {
+  Ossupload(file, "KxsAdmin/UploadImg").then((res: Res) => {
+    fileList.value.push({ name: cropperImgName.value, url: res.url });
+    UrlList.value.push(res.uploadurl);
+
+
+    props.callBack(UrlList.value.join(","));
+  });
+};
+</script>

+ 6 - 6
src/components/Uploadfile/index.vue

@@ -1,16 +1,16 @@
 <!--
  * @Author: Gui
  * @Date: 2023-05-12 11:36:28
- * @LastEditors: Please set LastEditors
- * @LastEditTime: 2023-06-06 14:57:14
+ * @LastEditors: guicheng 1625811865@qq.com
+ * @LastEditTime: 2024-06-20 15:36:35
  * @Description: kxs files
  * @filePath: 
 -->
 <template>
   <el-button type="primary" @click="clickupload">
     {{ btntext }}
-    <slot
-  /></el-button>
+    <slot />
+  </el-button>
   <input type="file" id="inputfile" style="display: none" />
 </template>
 <script lang="ts" setup>
@@ -31,8 +31,8 @@ onMounted(() => {
   uploaddo.value = document.querySelector("#inputfile");
   uploaddo.value.addEventListener("change", function (evt) {
     const file = evt.target.files[0];
-    Ossupload(file).then((res: Res) => {
-      props.FilePath(res.uploadurl);
+    Ossupload(file, "KxsAdmin/UploadFile").then((res: Res) => {
+      props.FilePath(res.url);
     });
   });
 });

+ 12 - 2
src/style/element-plus.scss

@@ -2,8 +2,14 @@
 .el-breadcrumb__inner a {
   font-weight: 400 !important;
 }
-el-text{display: flex;justify-content: center;align-items: center;
-  .el-icon{margin-right: 4px;}}
+el-text {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  .el-icon {
+    margin-right: 4px;
+  }
+}
 .el-upload {
   input[type="file"] {
     display: none !important;
@@ -42,6 +48,10 @@ el-text{display: flex;justify-content: center;align-items: center;
   margin-left: 2px !important;
 }
 
+.edit-btn {
+  width: 100%;
+}
+
 /* 自定义 popover 的类名 */
 .pure-popper {
   padding: 0 !important;

+ 4 - 5
src/utils/OSSupload.ts

@@ -1,8 +1,8 @@
 /*
  * @Author: Gui
  * @Date: 2023-03-01 19:20:44
- * @LastEditors: Please set LastEditors
- * @LastEditTime: 2023-06-06 15:10:19
+ * @LastEditors: guicheng 1625811865@qq.com
+ * @LastEditTime: 2024-06-20 14:43:25
  * @Description: kxs files
  * @filePath:
  */
@@ -33,7 +33,7 @@ const Ossupload = function (data, Filename = "KxsAdmin/upload") {
       region: "oss-cn-chengdu",
       accessKeyId: res.data.AccessId,
       accessKeySecret: res.data.AccessKey,
-      bucket: "kexiaoshuang"
+      bucket: "kexiaoshuang-oss"
     });
     const headers = {};
     const filetype = data.name.split(".")[data.name.split(".").length - 1];
@@ -41,8 +41,7 @@ const Ossupload = function (data, Filename = "KxsAdmin/upload") {
       md5(new Date().getTime() + data.size).substring(8, 24) + "." + filetype;
     try {
       const result = await client.put(
-        `${Filename}/${filetype}/${new Date().getFullYear()}/${
-          new Date().getMonth() + 1
+        `${Filename}/${filetype}/${new Date().getFullYear()}/${new Date().getMonth() + 1
         }/${new Date().getDate()}/${filename}`,
         data,
         { headers }

+ 2 - 2
src/utils/getUrl/getUrl.js

@@ -64,7 +64,7 @@ const getURL = () => {
 const getAllPlate = () => {
   return new Promise(async (resolve, reject) => {
     postRequest(
-      "http://localhost:5296/noauth/apiinfo/groupsforadmin",
+      "http://test.skbconfig.kexiaoshuang.com/api/apiinfo/groupsforadmin",
       {
         key: "kxs#2024"
       }
@@ -99,7 +99,7 @@ const getGroupUrl = async (checkPlate = []) => {
       );
     }, 5000);
     postRequest(
-      "http://localhost:5296/noauth/apiinfo/listforadmin",
+      "http://test.skbconfig.kexiaoshuang.com/api/apiinfo/listforadmin",
       parameters
     )
       .then(async res => {

+ 1 - 1
src/utils/http/index.ts

@@ -366,7 +366,7 @@ class PureHttp {
     const param = { data: {} };
     return this.request(
       "delete",
-      `${url}/${encryptByDES(String(params))}`,
+      `${url}/${encryptByDES(params)}`,
       param,
       config
     );

+ 25 - 0
src/utils/importUsed.ts

@@ -0,0 +1,25 @@
+/*
+ * @Author: guicheng 1625811865@qq.com
+ * @Date: 2024-06-21 11:11:08
+ * @LastEditors: guicheng 1625811865@qq.com
+ * @LastEditTime: 2024-06-21 11:55:32
+ * @FilePath: /admin-skb/src/utils/importUsed.ts
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ */
+
+import { inject, reactive, ref, onMounted } from "vue";
+import Uploadfile from "@/components/Uploadfile/index.vue";
+import UploadImg from "@/components/UploadImg/index.vue";
+import Editor from "@/components/Editor/index.vue";
+import { useRenderIcon } from "@/components/ReIcon/src/hooks";
+import { ElMessage, ElMessageBox } from "element-plus";
+import Upload from "@iconify-icons/ri/upload-2-fill";
+import Close from "@iconify-icons/ri/close-fill";
+import { http } from "@/utils/http";
+import { getGroupUrl } from "@/utils/getUrl/getUrl";
+import verification, { RegularVerification } from "./rules";
+import { type PaginationProps } from "@pureadmin/table";
+import { hasAuth } from "@/router/utils";
+import { PureTableBar } from "@/components/RePureTableBar";
+
+export { inject, onMounted, reactive, ref, Uploadfile, UploadImg, Editor, useRenderIcon, ElMessage, ElMessageBox, Upload, Close, http, getGroupUrl, RegularVerification, verification, PaginationProps, hasAuth, PureTableBar }

+ 90 - 0
src/utils/rules.ts

@@ -0,0 +1,90 @@
+/*
+ * @Author: Gui
+ * @Date: 2023-04-07 16:09:33
+ * @LastEditors: guicheng 1625811865@qq.com
+ * @LastEditTime: 2024-06-21 10:44:32
+ * @Description: kxs files
+ * @filePath:
+ */
+
+export function RegularVerification(zz: any, value: any, callback: any) {
+  const reg = zz;
+  if (!reg.test(value)) {
+    callback(new Error('请输入正确格式'))
+  }
+}
+
+const verification = {
+  //姓名
+  verificationName: (value: any, callback: any) => {
+    const reg = /^(?:[\u4e00-\u9fa5·]{2,16})$/;
+    if (!reg.test(value) && value) {
+      callback(new Error('请输入姓名'))
+    }
+  },
+  //银行卡号
+  verificationBankCard: (value: any, callback: any) => {
+    const reg = /^[1-9]\d{9,29}$/;
+    if (!reg.test(value) && value) {
+      callback(new Error('请输入正确的银行卡号'))
+    }
+  },
+  //手机号码
+  verificationPhonenNmber: (value: any, callback: any) => {
+    const reg = /^((13[0-9])|(14(0|[5-7]|9))|(15([0-3]|[5-9]))|(16(2|[5-7]))|(17[0-8])|(18[0-9])|(19([0-3]|[5-9])))\d{8}$/;
+    if (!reg.test(value) && value) {
+      callback(new Error('请输入正确手机号码'))
+    }
+  },
+  //6位短信验证码
+  verificationPhoneCode: (value: any, callback: any) => {
+    const reg = /^\d+$/;
+    if ((!reg.test(value) || value.length !== 6) && value) {
+      callback(new Error('请输入正确短信验证码'))
+    }
+  },
+  //邮箱
+  verificationEmail: (value: any, callback: any) => {
+    const reg = /^[A-Za-z0-9\u4e00-\u9fa5]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/;
+    if (!reg.test(value) && value) {
+      callback(new Error('请输入正确邮箱'))
+    }
+  },
+  //社会统一信用代码
+  verificationCreditCode: (value: any, callback: any) => {
+    const reg = /^(([0-9A-Za-z]{15})|([0-9A-Za-z]{18})|([0-9A-Za-z]{20}))$/;
+    if (!reg.test(value) && value) {
+      callback(new Error('请输入正确社会统一信用代码'))
+    }
+  },
+  //身份证号码
+  verificationIdCardNumber: (value: any, callback: any) => {
+    const reg = /^[1-9]\d{5}(?:18|19|20)\d{2}(?:0[1-9]|10|11|12)(?:0[1-9]|[1-2]\d|30|31)\d{3}[\dXx]$/;
+    if (!reg.test(value) && value) {
+      callback(new Error('请输入正确身份证号码'))
+    }
+  },
+  //链接地址
+  verificationUrl: (value: any, callback: any) => {
+    const reg = /(http|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?/;
+    if (!reg.test(value) && value) {
+      callback(new Error('请输入正确链接地址'))
+    }
+  },
+  //整数
+  verificationInteger: (value: any, callback: any) => {
+    const reg = /^(?:0|(?:-?[1-9]\d*))$/;
+    if (!reg.test(value) && value) {
+      callback(new Error('请输入整数'))
+    }
+  },
+  //浮点数
+  verificationFloat: (value: any, callback: any) => {
+    const reg = /^(-?[1-9]\d*\.\d+|-?0\.\d*[1-9]\d*|0\.0+)$/;
+    if (!reg.test(value) && value) {
+      callback(new Error('请输入浮点数'))
+    }
+  },
+}
+
+export default verification