Browse Source

批量删除前提示,上传组件

wangwei 4 years ago
parent
commit
7bf1ea8b17

+ 3 - 3
.env.development

@@ -7,7 +7,7 @@ VITE_USE_MOCK = true
 VITE_PUBLIC_PATH = /
 
 # Cross-domain proxy, you can configure multiple
-VITE_PROXY=[["/api","http://localhost:3000"],["/upload","http://localhost:3001/upload"]]
+VITE_PROXY=[["/api","http://localhost:8888"],["/upload","http://localhost:3001/upload"]]
 # VITE_PROXY=[["/api","https://vvbin.cn/test"]]
 
 # Delete console
@@ -16,11 +16,11 @@ VITE_DROP_CONSOLE = false
 # Basic interface address SPA
 # VITE_GLOB_API_URL= http://localhost:8000/api
 # VITE_GLOB_API_URL=http://139.186.154.72:8888/
-VITE_GLOB_API_URL=http://localhost:8888/admin
+VITE_GLOB_API_URL=
 # VITE_GLOB_API_URL=/api
 
 # File upload address, optional
 VITE_GLOB_UPLOAD_URL=http://localhost:8888/admin/upload
 
 # Interface prefix
-VITE_GLOB_API_URL_PREFIX=
+VITE_GLOB_API_URL_PREFIX= http://localhost:8888/admin

+ 1 - 1
.vscode/launch.json

@@ -5,7 +5,7 @@
       "type": "chrome",
       "request": "launch",
       "name": "Launch Chrome",
-      "url": "http://localhost:3100",
+      "url": "http://localhost:8888",
       "webRoot": "${workspaceFolder}/src",
       "sourceMaps": true
     },

+ 5 - 4
src/api/sys/upload.ts

@@ -3,8 +3,11 @@ import { defHttp } from '/@/utils/http/axios';
 import { UploadFileParams } from '/@/utils/http/axios/types';
 import { useGlobSetting } from '/@/hooks/setting';
 
-const { uploadUrl = '' } = useGlobSetting();
+const { uploadUrl = '', urlPrefix } = useGlobSetting();
 
+enum Api {
+  uploadUrl = '/general/file',
+}
 /**
  * @description: Upload interface
  */
@@ -12,11 +15,9 @@ export function uploadApi(
   params: UploadFileParams,
   onUploadProgress: (progressEvent: ProgressEvent) => void
 ) {
-  console.log(`params`, params);
-  console.log(`uploadUrl`, uploadUrl);
   return defHttp.uploadFile<UploadApiResult>(
     {
-      url: uploadUrl,
+      url: urlPrefix + Api.uploadUrl,
       onUploadProgress,
     },
     params

+ 21 - 1
src/components/Upload/src/BasicUpload.vue

@@ -4,6 +4,15 @@
       <a-button type="primary" @click="openUploadModal" preIcon="carbon:cloud-upload">
         {{ t('component.upload.upload') }}
       </a-button>
+      <a-button
+        v-if="showChooseBtn"
+        class="choose-btn"
+        type="danger"
+        @click="openChooseModal"
+        preIcon="carbon:cloud-upload"
+      >
+        {{ t('component.upload.choose') }}
+      </a-button>
       <Tooltip placement="bottom" v-if="showPreview">
         <template #title>
           {{ t('component.upload.uploaded') }}
@@ -52,7 +61,7 @@
     name: 'BasicUpload',
     components: { UploadModal, UploadPreviewModal, Icon, Tooltip },
     props: uploadContainerProps,
-    emits: ['change'],
+    emits: ['change', 'openChooseModal'],
 
     setup(props, { emit, attrs }) {
       const { t } = useI18n();
@@ -95,9 +104,14 @@
         emit('change', fileListRef.value);
       }
 
+      function openChooseModal() {
+        emit('openChooseModal');
+      }
+
       return {
         registerUploadModal,
         openUploadModal,
+        openChooseModal,
         handleChange,
         handlePreviewChange,
         registerPreviewModal,
@@ -106,7 +120,13 @@
         showPreview,
         bindValue,
         t,
+        props,
       };
     },
   });
 </script>
+<style scoped>
+  .choose-btn {
+    margin-left: 5px !important;
+  }
+</style>

+ 4 - 0
src/components/Upload/src/props.ts

@@ -50,6 +50,10 @@ export const uploadContainerProps = {
     type: Boolean as PropType<boolean>,
     default: false,
   },
+  showChooseBtn: {
+    type: Boolean,
+    default: false,
+  },
 };
 
 export const previewProps = {

+ 1 - 1
src/components/customComponents/imageData.tsx

@@ -7,7 +7,7 @@ import {
 } from '/@/components/Upload/src/helper';
 
 import TableAction from '/@/components/Table/src/components/TableAction.vue';
-import ThumbUrl from './ThumbUrl.vue';
+import ThumbUrl from '/@/components/customComponents/ThumbUrl.vue';
 import { useI18n } from '/@/hooks/web/useI18n';
 const { t } = useI18n();
 

+ 1 - 1
src/locales/lang/en/component.ts

@@ -82,7 +82,7 @@ export default {
     saveError: 'There is no file successfully uploaded and cannot be saved!',
 
     preview: 'Preview',
-    choose: 'Select the file',
+    choose: 'Select',
 
     accept: 'Support {0} format',
     acceptUpload: 'Only upload files in {0} format',

+ 1 - 1
src/locales/lang/zh_CN/component.ts

@@ -85,7 +85,7 @@ export default {
     saveError: '没有上传成功的文件,无法保存!',
 
     preview: '预览',
-    choose: '选择文件',
+    choose: '选择',
 
     accept: '支持{0}格式',
     acceptUpload: '只能上传{0}格式文件',

+ 25 - 7
src/views/admin/admin/index.vue

@@ -35,12 +35,14 @@
   </CollapseContainer>
 </template>
 <script lang="ts">
-  import { defineComponent, reactive, ref, toRefs, unref } from 'vue';
+  import { defineComponent, reactive, ref, toRefs, unref, createVNode } from 'vue';
   import { CollapseContainer } from '/@/components/Container/index';
   import Popup from './popup.vue';
   import { useMessage } from '/@/hooks/web/useMessage';
   import { useModal } from '/@/components/Modal';
   import { jsonToSheetXlsx, ExpExcelModel, ExportModalResult } from '/@/components/Excel';
+  import { Modal } from 'ant-design-vue';
+  import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
   import { getFormConfig, columns } from './data';
   import {
     getUserList,
@@ -233,15 +235,31 @@
       }
 
       async function deleteBatches() {
-        const ids = getTableAction().getSelectRowKeys().toString();
+        const keys = await getTableAction().getSelectRowKeys();
+        const count = keys.length;
+        const ids = keys.toString();
         if (!ids) {
           return;
         }
-        await deleteBatchesUser({ ids }).then((res) => {
-          console.log(res);
-          getTableAction().reload();
-          success('删除成功!');
-          getTableAction().setSelectedRowKeys([]);
+        Modal.confirm({
+          title: '删除提示',
+          icon: createVNode(ExclamationCircleOutlined),
+          content: '确定删除选中的' + count + '项?',
+          okText: '确定',
+          okType: 'danger',
+          cancelText: '取消',
+          maskClosable: true,
+          async onOk() {
+            await deleteBatchesUser({ ids }).then((res) => {
+              console.log(res);
+              getTableAction().reload();
+              success('删除成功!');
+              getTableAction().setSelectedRowKeys([]);
+            });
+          },
+          onCancel() {
+            console.log('Cancel');
+          },
         });
       }
 

+ 25 - 7
src/views/admin/group/index.vue

@@ -30,7 +30,7 @@
   </CollapseContainer>
 </template>
 <script lang="ts">
-  import { defineComponent, reactive, ref, toRefs, unref, nextTick } from 'vue';
+  import { defineComponent, reactive, ref, toRefs, unref, nextTick, createVNode } from 'vue';
   import { CollapseContainer } from '/@/components/Container/index';
   import Popup from './popup.vue';
   import { useModal } from '/@/components/Modal';
@@ -38,6 +38,8 @@
   import { useUserStore } from '/@/store/modules/user';
   import { useMessage } from '/@/hooks/web/useMessage';
   import { jsonToSheetXlsx, ExpExcelModel, ExportModalResult } from '/@/components/Excel';
+  import { Modal } from 'ant-design-vue';
+  import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
   import {
     getGroupTree,
     addGroup,
@@ -203,15 +205,31 @@
       }
 
       async function deleteBatches() {
-        const ids = getTableAction().getSelectRowKeys().toString();
+        const keys = await getTableAction().getSelectRowKeys();
+        const count = keys.length;
+        const ids = keys.toString();
         if (!ids) {
           return;
         }
-        await deleteBatchesGroup({ ids }).then(() => {
-          getTableAction().reload();
-          ExpandAllRows();
-          success('删除成功!');
-          getTableAction().setSelectedRowKeys([]);
+        Modal.confirm({
+          title: '删除提示',
+          icon: createVNode(ExclamationCircleOutlined),
+          content: '确定删除选中的' + count + '项?',
+          okText: '确定',
+          okType: 'danger',
+          cancelText: '取消',
+          maskClosable: true,
+          async onOk() {
+            await deleteBatchesGroup({ ids }).then(() => {
+              getTableAction().reload();
+              ExpandAllRows();
+              success('删除成功!');
+              getTableAction().setSelectedRowKeys([]);
+            });
+          },
+          onCancel() {
+            console.log('Cancel');
+          },
         });
       }
 

+ 26 - 8
src/views/admin/rule/index.vue

@@ -32,7 +32,7 @@
 </template>
 <script lang="ts">
   import { usePermission } from '/@/hooks/web/usePermission';
-  import { defineComponent, reactive, ref, toRefs, unref, nextTick } from 'vue';
+  import { defineComponent, reactive, ref, toRefs, unref, nextTick, createVNode } from 'vue';
   import { CollapseContainer } from '/@/components/Container/index';
   import Popup from './popup.vue';
   import { useModal } from '/@/components/Modal';
@@ -40,6 +40,8 @@
   import { columns } from './data';
   import { getRuleTree, addRule, editRule, deleteRule, deleteBatchesRule } from '/@/api/sys/user';
   import { jsonToSheetXlsx, ExpExcelModel, ExportModalResult } from '/@/components/Excel';
+  import { Modal } from 'ant-design-vue';
+  import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
   import {
     BasicTable,
     useTable,
@@ -173,16 +175,32 @@
       }
 
       async function deleteBatches() {
-        const ids = getTableAction().getSelectRowKeys().toString();
+        const keys = await getTableAction().getSelectRowKeys();
+        const count = keys.length;
+        const ids = keys.toString();
         if (!ids) {
           return;
         }
-        await deleteBatchesRule({ ids }).then(() => {
-          getTableAction().reload();
-          getTableAction().setSelectedRowKeys([]);
-          reloadMenu();
-          ExpandAllRows();
-          success('删除成功!');
+        Modal.confirm({
+          title: '删除提示',
+          icon: createVNode(ExclamationCircleOutlined),
+          content: '确定删除选中的' + count + '项?',
+          okText: '确定',
+          okType: 'danger',
+          cancelText: '取消',
+          maskClosable: true,
+          async onOk() {
+            await deleteBatchesRule({ ids }).then(() => {
+              getTableAction().reload();
+              getTableAction().setSelectedRowKeys([]);
+              reloadMenu();
+              ExpandAllRows();
+              success('删除成功!');
+            });
+          },
+          onCancel() {
+            console.log('Cancel');
+          },
         });
       }
 

+ 173 - 0
src/views/general/config/customComponents/ChooseModal.vue

@@ -0,0 +1,173 @@
+<template>
+  <BasicModal
+    width="800px"
+    :title="t('component.upload.choose')"
+    v-bind="$attrs"
+    @register="register"
+    :showOkBtn="false"
+    cancelText="关闭"
+  >
+    <a-button type="primary" preIcon="mdi:reload" iconSize="20" @click="reload" />
+    <a-button class="check-btn" type="success" @click="checked"> 选择 </a-button>
+    <BasicTable ref="tableRef" @register="registerTable" rowKey="id" @rowDbClick="handleDetail">
+      <template #action="{ record, column }">
+        <TableAction :actions="createActions(record, column)" />
+      </template>
+    </BasicTable>
+  </BasicModal>
+</template>
+<script lang="ts">
+  import { defineComponent, PropType, ref, toRefs, unref } from 'vue';
+  import { BasicModal, useModalInner } from '/@/components/Modal';
+  import { adapt } from '/@/utils/adapt';
+  import { useI18n } from '/@/hooks/web/useI18n';
+  import {
+    BasicTable,
+    useTable,
+    TableAction,
+    ActionItem,
+    EditRecordRow,
+    TableActionType,
+  } from '/@/components/Table';
+  import { columns } from './chooseModalData';
+  interface PopupData {
+    title: string;
+  }
+  const formData = [
+    {
+      id: 1,
+      username: 'test1',
+      title: '日志1',
+      url: 'http://localhost:3100/#/permission/admin',
+      ip: '0.0.0.0',
+      browser: 'Mozilla/5.0',
+      time: '2020-10-20',
+    },
+    {
+      id: 2,
+      username: 'test2',
+      title: '日志2',
+      url: 'http://localhost:3100/#/permission/admin',
+      ip: '0.0.0.0',
+      browser: 'Mozilla/5.0',
+      time: '2020-10-21',
+    },
+    {
+      id: 3,
+      username: 'test3',
+      title: '日志3',
+      url: 'http://localhost:3100/#/permission/admin',
+      ip: '0.0.0.0',
+      browser: 'Mozilla/5.0',
+      time: '2020-10-21',
+    },
+  ];
+
+  export default defineComponent({
+    components: { BasicModal, BasicTable, TableAction },
+    props: {
+      popupData: {
+        type: Object as PropType<PopupData>,
+        default: () => {},
+      },
+    },
+    setup(props) {
+      const { t } = useI18n();
+      const popupData = props.popupData as PopupData;
+      const tableRef = ref<Nullable<TableActionType>>(null);
+      const currentEditKeyRef = ref('');
+      const modelRef = ref({});
+      const adaptWidth = adapt();
+      const [register] = useModalInner((data) => {
+        // 方式2
+        modelRef.value = data;
+      });
+      const [registerTable] = useTable({
+        // title: '管理员日志',
+        // titleHelpMessage: '',
+        rowSelection: { type: 'checkbox' },
+        columns: columns,
+        clickToRowSelect: false, // 点击行不勾选
+        // api: getUserList,
+        dataSource: formData,
+        actionColumn: {
+          width: 160,
+          title: '操作',
+          dataIndex: 'action',
+          slots: { customRender: 'action' },
+          fixed: undefined,
+        },
+        showIndexColumn: false,
+        bordered: true,
+      });
+      function getTableAction() {
+        // 获取组件
+        const tableAction = unref(tableRef);
+        if (!tableAction) {
+          throw new Error('tableAction is null');
+        }
+        return tableAction;
+      }
+
+      function getSelectRowList() {
+        // 获取选中行
+        console.log(getTableAction().getSelectRows());
+      }
+      function getSelectRowKeyList() {
+        // 获取选中行的key --- id
+        console.log(getTableAction().getSelectRowKeys());
+      }
+
+      function handleChecked(record: EditRecordRow) {
+        currentEditKeyRef.value = record.id; // record.key
+
+        const data = getTableAction().getDataSource();
+        data.map((item) => {
+          if (item.id === record.id) {
+            record = item;
+          }
+        });
+      }
+      function checked(record: EditRecordRow) {
+        currentEditKeyRef.value = record.id; // record.key
+
+        const data = getTableAction().getDataSource();
+        data.map((item) => {
+          if (item.id === record.id) {
+            record = item;
+          }
+        });
+      }
+
+      function createActions(record: EditRecordRow): ActionItem[] {
+        return [
+          {
+            label: '选择',
+            icon: 'akar-icons:eye-open',
+            color: 'success',
+            onClick: handleChecked.bind(null, record),
+          },
+        ];
+      }
+
+      return {
+        register,
+        registerTable,
+        adaptWidth,
+        checked,
+        createActions,
+        getTableAction,
+        getSelectRowList,
+        getSelectRowKeyList,
+        model: modelRef,
+        t,
+        ...toRefs(popupData),
+      };
+    },
+  });
+</script>
+<style lang="less">
+  .check-btn {
+    margin-left: 5px !important;
+  }
+</style>

+ 43 - 0
src/views/general/config/customComponents/UploadImage.vue

@@ -0,0 +1,43 @@
+<template>
+  <div style="display: flex">
+    <BasicUpload
+      :showChooseBtn="true"
+      :maxSize="20"
+      :maxNumber="10"
+      @change="handleChange"
+      @openChooseModal="openChooseModal"
+      :api="uploadApi"
+      class="my-5"
+    />
+    <ChooseModal @register="chooseModalRegister" />
+  </div>
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { BasicUpload } from '/@/components/Upload';
+  import { useMessage } from '/@/hooks/web/useMessage';
+  import { uploadApi } from '/@/api/sys/upload';
+  import ChooseModal from './ChooseModal.vue';
+  import { useModal } from '/@/components/Modal';
+
+  export default defineComponent({
+    components: { BasicUpload, ChooseModal },
+    setup() {
+      const { createMessage } = useMessage();
+      const [chooseModalRegister, { openModal }] = useModal();
+      function openChooseModal() {
+        console.log('=======openChooseModal=======');
+        openModal(true);
+      }
+      return {
+        handleChange: (list: string[]) => {
+          createMessage.info(`已上传文件${JSON.stringify(list)}`);
+        },
+        openChooseModal,
+        uploadApi,
+        chooseModalRegister,
+        openModal,
+      };
+    },
+  });
+</script>

+ 46 - 0
src/views/general/config/customComponents/chooseModalData.ts

@@ -0,0 +1,46 @@
+import { BasicColumn } from '/@/components/Table';
+import { FileItem } from '/@/components/Upload/src/types';
+import { h } from 'vue';
+import ThumbUrl from '/@/components/customComponents/ThumbUrl.vue';
+
+export const columns: BasicColumn[] = [
+  {
+    title: 'ID',
+    dataIndex: 'id',
+    editComponentProps: {
+      prefix: '$',
+    },
+    width: 100,
+  },
+  {
+    dataIndex: 'thumbUrl',
+    title: '预览',
+    width: 70,
+    customRender: ({ record }) => {
+      const { thumbUrl } = (record as FileItem) || {};
+      return h(ThumbUrl, {
+        fileUrl: thumbUrl,
+      });
+    },
+  },
+  {
+    title: '宽度',
+    dataIndex: 'width',
+    width: 150,
+  },
+  {
+    title: '高度',
+    dataIndex: 'height',
+    width: 150,
+  },
+  {
+    title: 'Mime类型',
+    dataIndex: 'type',
+    width: 150,
+  },
+  {
+    title: '创建时间',
+    dataIndex: 'time',
+    width: 150,
+  },
+];

+ 11 - 3
src/views/general/config/data.ts

@@ -13,6 +13,7 @@ import Radio from './customComponents/Radio.vue';
 import DatePicker from './customComponents/DatePicker.vue';
 import TimePicker from './customComponents/TimePicker.vue';
 import Switch from './customComponents/Switch.vue';
+import UploadImage from './customComponents/UploadImage.vue';
 import { configNameExist } from '/@/api/sys/general';
 
 export const columns: BasicColumn[] = [
@@ -148,6 +149,13 @@ export const columns: BasicColumn[] = [
             // style: { width: '65%' },
             onChange: onArrayChange,
           });
+        case 'image':
+          return h(UploadImage, {
+            value: record.value,
+            // options: record.content,
+            // style: { width: '65%' },
+            // onChange: onArrayChange,
+          });
       }
     },
   },
@@ -204,11 +212,11 @@ export const schemas: FormSchema[] = [
         },
         {
           label: '图片',
-          value: 'pic',
+          value: 'image',
         },
         {
           label: '图片(多)',
-          value: 'mutiplePic',
+          value: 'images',
         },
         {
           label: '文件',
@@ -216,7 +224,7 @@ export const schemas: FormSchema[] = [
         },
         {
           label: '文件(多)',
-          value: 'multipleFile',
+          value: 'files',
         },
         {
           label: '开关',

+ 15 - 5
src/views/table/attachment/index.vue

@@ -33,6 +33,12 @@
     EditRecordRow,
     TableActionType,
   } from '/@/components/Table';
+  import {
+    // downloadByUrl,
+    // downloadByData,
+    // downloadByBase64,
+    downloadByOnlineUrl,
+  } from '/@/utils/file/download';
 
   interface ModelData {
     title: string;
@@ -56,19 +62,21 @@
         dataSource: [
           {
             id: 1,
-            name: '文件1',
+            name: '文件1.jpg',
             thumbUrl:
               'https://dss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=1999921673,816131569&fm=26&gp=0.jpg',
             size: 1504,
+            type: 'jpg',
           },
           {
             id: 2,
             thumbUrl:
               'https://dss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=2496571732,442429806&fm=26&gp=0.jpg',
-            name: '未知',
-            size: 351,
+            name: '未知.jpg',
+            type: 'jpg',
+            size: 442368,
           },
-          { id: 3, name: '文件2', addr: '未知地点', size: 155528 },
+          { id: 3, name: '文件2', thumbUrl: '', size: 0 },
         ],
         showIndexColumn: false,
         actionColumn: createPreviewActionColumn(handleRemove, handleDownload),
@@ -145,7 +153,9 @@
       function handleDownload(record: FileItem) {
         console.log('点击了下载');
         console.log(record);
-        console.log('点击了下载');
+        const fileUrl = record.thumbUrl as string;
+        const fileName = record.name;
+        downloadByOnlineUrl(fileUrl, fileName);
       }
 
       function handleDelete(record: Recordable) {