Quellcode durchsuchen

refactor: 组件迁移到@dage/web-components

chenlei vor 2 Jahren
Ursprung
Commit
b99ed9aacf

+ 3 - 2
package.json

@@ -4,8 +4,9 @@
   "version": "0.1.0",
   "private": true,
   "dependencies": {
-    "@amap/amap-react": "^0.1.5",
+    "@ant-design/icons": "^5.1.4",
     "@babel/core": "^7.16.0",
+    "@dage/web-components": "^1.0.2",
     "@pmmmwh/react-refresh-webpack-plugin": "^0.5.3",
     "@svgr/webpack": "^5.5.0",
     "@testing-library/jest-dom": "^5.16.5",
@@ -13,7 +14,7 @@
     "@testing-library/user-event": "^13.5.0",
     "@types/jest": "^27.5.2",
     "@types/node": "^16.18.38",
-    "@types/react": "^18.2.14",
+    "@types/react": "^18.2.16",
     "@types/react-dom": "^18.2.6",
     "antd": "^5.6.4",
     "axios": "^1.4.0",

+ 1 - 1
src/api/history.ts

@@ -5,7 +5,7 @@ import {
   GetHistoryListResponse,
   HistoryDictItem,
 } from "@/types";
-import service from "@/utils/services";
+import { service } from "@dage/web-components";
 
 export const historyApi = {
   getHistoryDictList: () => {

+ 1 - 1
src/api/index.ts

@@ -1,5 +1,5 @@
 import { LoginRequest, LoginResponse, UpdatePwdRequest } from "@/types";
-import service from "@/utils/services";
+import { service } from "@dage/web-components";
 
 export const login = (data: LoginRequest) => {
   return service.post<LoginResponse>("/api/admin/login", data);

+ 1 - 1
src/api/industrial-meta.ts

@@ -1,5 +1,5 @@
 import { GetIndustrialMetaListParams, IndustrialMetaItemType } from "@/types";
-import service from "@/utils/services";
+import { service } from "@dage/web-components";
 
 export const industrialMetaApi = {
   getList(params: GetIndustrialMetaListParams) {

+ 1 - 1
src/api/log.ts

@@ -1,5 +1,5 @@
 import { GetLogListParams } from "@/types";
-import service from "@/utils/services";
+import { service } from "@dage/web-components";
 
 export const logApi = {
   getList(params: GetLogListParams) {

+ 1 - 1
src/api/overview.ts

@@ -4,7 +4,7 @@ import {
   GetOverviewListResponse,
   OverviewParams,
 } from "@/types";
-import service from "@/utils/services";
+import { service } from "@dage/web-components";
 
 export const overviewApi = {
   getList(data: GetOverviewListParams) {

+ 1 - 1
src/api/user.ts

@@ -1,5 +1,5 @@
 import { GetUserListParams, SaveUserType } from "@/types";
-import service from "@/utils/services";
+import { service } from "@dage/web-components";
 
 export const userApi = {
   getList(params: GetUserListParams) {

+ 1 - 1
src/api/weapon.ts

@@ -1,5 +1,5 @@
 import { AddWeaponParams, HistoryDictItem } from "@/types";
-import service from "@/utils/services";
+import { service } from "@dage/web-components";
 
 export const weaponApi = {
   getDictList() {

+ 0 - 8
src/components/DageFileCheckbox/constants.ts

@@ -1,8 +0,0 @@
-import { DageUploadType } from "../DageUpload";
-
-export const DAGE_FILE_CHECKBOX_OPTIONS = [
-  { label: "模型", value: DageUploadType.MODEL },
-  { label: "图片", value: DageUploadType.IMG },
-  { label: "音频", value: DageUploadType.AUDIO },
-  { label: "视频", value: DageUploadType.VIDEO },
-];

+ 0 - 32
src/components/DageFileCheckbox/index.module.scss

@@ -1,32 +0,0 @@
-.dageFileContainer {
-  margin-top: 15px;
-}
-
-.dageFileCheckboxGroup {
-  display: flex;
-  align-items: center;
-  height: 32px;
-}
-
-.dageFileItem {
-  display: flex;
-  align-items: flex-start;
-
-  &:not(:first-child) {
-    margin-top: 15px;
-  }
-  > span {
-    margin-right: 5px;
-    line-height: 32px;
-
-    &::before {
-      display: inline-block;
-      margin-inline-end: 4px;
-      color: #ff4d4f;
-      font-size: 14px;
-      font-family: SimSun, sans-serif;
-      line-height: 1;
-      content: "*";
-    }
-  }
-}

+ 0 - 206
src/components/DageFileCheckbox/index.tsx

@@ -1,206 +0,0 @@
-import { Checkbox } from "antd";
-import {
-  forwardRef,
-  useCallback,
-  useEffect,
-  useImperativeHandle,
-  useMemo,
-  useState,
-} from "react";
-import { CheckboxValueType } from "antd/lib/checkbox/Group";
-import style from "./index.module.scss";
-import { DAGE_FILE_CHECKBOX_OPTIONS } from "./constants";
-import { DageFileCheckboxMethods, DageFileCheckboxProps } from "./types";
-import {
-  DageFileResponseType,
-  DageUpload,
-  DageUploadType,
-} from "../DageUpload";
-
-export const DageFileCheckbox = forwardRef<
-  DageFileCheckboxMethods,
-  DageFileCheckboxProps
->(({ value, action, disabled, onChange, onFileChange }, ref) => {
-  const checkboxVal = useMemo(() => (value ? value.split(",") : []), [value]);
-  const [modelFiles, setModelFiles] = useState<DageFileResponseType[]>([]);
-  const [imgFiles, setImgFiles] = useState<DageFileResponseType[]>([]);
-  const [videoFiles, setVideoFiles] = useState<DageFileResponseType[]>([]);
-  const [audioFiles, setAudioFiles] = useState<DageFileResponseType[]>([]);
-
-  useImperativeHandle(ref, () => ({
-    async validate() {
-      if (hasModel && !modelFiles.length) {
-        throw new Error("模型文件不能为空");
-      } else if (hasImg && !imgFiles.length) {
-        throw new Error("图片文件不能为空");
-      } else if (hasAudio && !videoFiles.length) {
-        throw new Error("视频文件不能为空");
-      } else if (hasVideo && !audioFiles.length) {
-        throw new Error("音频文件不能为空");
-      }
-    },
-    setFileList(list) {
-      const stack: Record<string, DageFileResponseType[]> = {
-        [DageUploadType.MODEL]: [],
-        [DageUploadType.IMG]: [],
-        [DageUploadType.AUDIO]: [],
-        [DageUploadType.VIDEO]: [],
-      };
-
-      list.forEach((item) => {
-        stack[item.dType].push(item);
-      });
-
-      Object.keys(stack).forEach((key) => {
-        const list = stack[key];
-        if (!list.length) return;
-        switch (key) {
-          case DageUploadType.MODEL:
-            setModelFiles(list);
-            break;
-          case DageUploadType.IMG:
-            setImgFiles(list);
-            break;
-          case DageUploadType.AUDIO:
-            setAudioFiles(list);
-            break;
-          case DageUploadType.VIDEO:
-            setVideoFiles(list);
-            break;
-        }
-      });
-    },
-  }));
-
-  const hasModel = useMemo(
-    () => checkboxVal.includes(DageUploadType.MODEL),
-    [checkboxVal]
-  );
-  const hasImg = useMemo(
-    () => checkboxVal.includes(DageUploadType.IMG),
-    [checkboxVal]
-  );
-  const hasAudio = useMemo(
-    () => checkboxVal.includes(DageUploadType.AUDIO),
-    [checkboxVal]
-  );
-  const hasVideo = useMemo(
-    () => checkboxVal.includes(DageUploadType.VIDEO),
-    [checkboxVal]
-  );
-
-  const handleCheckbox = useCallback(
-    (val: CheckboxValueType[]) => {
-      onChange?.(val.join(","));
-    },
-    [onChange]
-  );
-
-  const handleFileChange = useCallback(
-    (
-      method: (v: DageFileResponseType[]) => void,
-      list: DageFileResponseType[]
-    ) => {
-      console.log(list);
-      method(list);
-    },
-    []
-  );
-
-  useEffect(() => {
-    onFileChange?.([
-      ...(hasModel ? modelFiles : []),
-      ...(hasImg ? imgFiles : []),
-      ...(hasVideo ? videoFiles : []),
-      ...(hasAudio ? audioFiles : []),
-    ]);
-  }, [
-    modelFiles,
-    imgFiles,
-    videoFiles,
-    audioFiles,
-    hasModel,
-    hasImg,
-    hasVideo,
-    hasAudio,
-    onFileChange,
-  ]);
-
-  return (
-    <div className={style.dageFileCheckbox}>
-      <Checkbox.Group
-        disabled={disabled}
-        className={style.dageFileCheckboxGroup}
-        value={checkboxVal}
-        options={DAGE_FILE_CHECKBOX_OPTIONS}
-        onChange={handleCheckbox}
-      />
-
-      <div className={style.dageFileContainer}>
-        {hasModel && (
-          <div className={style.dageFileItem}>
-            <span>模型:</span>
-            <DageUpload
-              disabled={disabled}
-              value={modelFiles}
-              action={action}
-              type={DageUploadType.MODEL}
-              maxCount={1}
-              maxSize={500}
-              tips="仅支持4dage格式的模型文件,大小不能超过500M"
-              onChange={handleFileChange.bind(undefined, setModelFiles)}
-            />
-          </div>
-        )}
-        {hasImg && (
-          <div className={style.dageFileItem}>
-            <span>图片:</span>
-            <DageUpload
-              disabled={disabled}
-              value={imgFiles}
-              action={action}
-              type={DageUploadType.IMG}
-              maxCount={9}
-              maxSize={20}
-              tips="支持png、jpg和jpeg格式;最大20M,最多9张"
-              onChange={handleFileChange.bind(undefined, setImgFiles)}
-            />
-          </div>
-        )}
-        {hasAudio && (
-          <div className={style.dageFileItem}>
-            <span>音频:</span>
-            <DageUpload
-              disabled={disabled}
-              value={audioFiles}
-              action={action}
-              type={DageUploadType.AUDIO}
-              maxCount={1}
-              maxSize={10}
-              tips="仅支持MP3格式的音频文件,大小不得超过10MB"
-              onChange={handleFileChange.bind(undefined, setAudioFiles)}
-            />
-          </div>
-        )}
-        {hasVideo && (
-          <div className={style.dageFileItem}>
-            <span>视频:</span>
-            <DageUpload
-              disabled={disabled}
-              value={videoFiles}
-              action={action}
-              type={DageUploadType.VIDEO}
-              maxCount={1}
-              maxSize={500}
-              tips="仅支持MP4格式的视频文件,大小不得超过500MB"
-              onChange={handleFileChange.bind(undefined, setVideoFiles)}
-            />
-          </div>
-        )}
-      </div>
-    </div>
-  );
-});
-
-export * from "./types";
-export * from "./constants";

+ 0 - 23
src/components/DageFileCheckbox/types.ts

@@ -1,23 +0,0 @@
-import { RuleObject } from "antd/es/form";
-import { DageFileResponseType } from "../DageUpload";
-
-export interface DageFileCheckboxMethods {
-  validate(
-    rule: RuleObject,
-    value: any,
-    callback: (error?: string | undefined) => void
-  ): Promise<void>;
-  setFileList(list: DageFileResponseType[]): void;
-}
-
-export interface DageFileCheckboxProps {
-  /**
-   * 选中文件类型
-   * @example model,video,audio
-   */
-  value?: string;
-  action: string;
-  disabled?: boolean;
-  onChange?(v: string): void;
-  onFileChange?(list: DageFileResponseType[]): void;
-}

+ 0 - 221
src/components/DageMap/index.tsx

@@ -1,221 +0,0 @@
-import {
-  forwardRef,
-  useCallback,
-  useImperativeHandle,
-  useMemo,
-  useRef,
-  useState,
-} from "react";
-import { Amap, Marker } from "@amap/amap-react";
-import { AutoComplete, Button, Input, Space } from "antd";
-import axios from "axios";
-import { debounce } from "lodash";
-import {
-  AMapGeocoderGetAddressResult,
-  AMapTipsResponse,
-  DageMapMethods,
-  DageMapPoisType,
-  DageMapProps,
-} from "./types";
-import { DageMapGeocoder } from "./plugins";
-
-export const DageMap = forwardRef<DageMapMethods, DageMapProps>(
-  (
-    { latitude, longitude, disabled, address, city, onChange, onMapComplete },
-    ref
-  ) => {
-    const mapRef = useRef<AMap.Map_2>();
-    const [loaded, setLoaded] = useState(false);
-    const [lng, setLng] = useState<number>(longitude);
-    const [lat, setLat] = useState<number>(latitude);
-    const [options, setOptions] = useState<DageMapPoisType[]>([]);
-    const position = useMemo(
-      () => [longitude, latitude],
-      [longitude, latitude]
-    );
-    const _onChange = useRef(onChange).current;
-
-    useImperativeHandle(ref, () => ({
-      mapRef: mapRef.current,
-    }));
-
-    const handleSearch = useMemo(
-      () =>
-        debounce(async (value: string) => {
-          if (!value) {
-            setOptions([]);
-            return;
-          }
-
-          const { data } = await axios.get<AMapTipsResponse>(
-            `https://restapi.amap.com/v3/assistant/inputtips?key=e98c2a32f09d82868faace9329e58c26&keywords=${value}&city=${city}&citylimit=true`
-          );
-          setOptions(data.tips);
-        }, 500),
-      [city]
-    );
-
-    const handleClick = useCallback(
-      (e: AMap.Map_2, data: any) => {
-        if (disabled) return;
-
-        const { lng, lat } = data.lnglat;
-        setLat(lat);
-        setLng(lng);
-        _onChange?.({
-          lat,
-          lng,
-        });
-      },
-      [_onChange, disabled]
-    );
-
-    /**
-     * 地图初始化完成
-     */
-    const handleComplete = useCallback(() => {
-      setLoaded(true);
-      mapRef.current?.setCenter([longitude, latitude], false, 1000);
-      onMapComplete?.();
-    }, [longitude, latitude, onMapComplete]);
-
-    const handleMarker = useMemo(
-      () =>
-        debounce((e: any) => {
-          const [lng, lat] = e._position;
-          setLat(lat);
-          setLng(lng);
-          _onChange?.({
-            lat,
-            lng,
-          });
-        }, 200),
-      [_onChange]
-    );
-
-    const handlePosition = useCallback(
-      (long = lng, lati = lat) => {
-        if (!long || !lati) return;
-        _onChange?.({
-          lat: lati,
-          lng: long,
-        });
-        mapRef.current?.setCenter([long, lati], false, 1000);
-      },
-      [lng, lat, _onChange]
-    );
-
-    const handleSelect = useCallback(
-      (val: string, opts: DageMapPoisType) => {
-        const [lng, lat] = opts.location.split(",").map((i) => Number(i));
-        setLng(lng);
-        setLat(lat);
-
-        handlePosition(lng, lat);
-
-        _onChange?.({
-          lat,
-          lng,
-        });
-      },
-      [handlePosition, _onChange]
-    );
-
-    const handleAutoCompleteChange = useCallback(
-      (val: string) => {
-        _onChange?.({
-          address: val,
-        });
-      },
-      [_onChange]
-    );
-
-    const handleGeocoderAddress = useCallback(
-      (res: AMapGeocoderGetAddressResult) => {
-        _onChange?.({
-          address: res.regeocode.formattedAddress,
-        });
-      },
-      [_onChange]
-    );
-
-    return (
-      <>
-        <div>
-          <AutoComplete
-            allowClear
-            disabled={disabled}
-            value={address}
-            style={{ width: 450 }}
-            options={options.map((i) => ({
-              ...i,
-              value: i.name,
-            }))}
-            onSearch={handleSearch}
-            onSelect={handleSelect}
-            onChange={handleAutoCompleteChange}
-          >
-            <Input allowClear placeholder="请输入详细描述" />
-          </AutoComplete>
-        </div>
-
-        <Space style={{ margin: "15px 0" }}>
-          <Input
-            readOnly={disabled}
-            value={lng}
-            type="number"
-            placeholder="请输入经度"
-            onChange={(e) => setLng(Number(e.target.value))}
-          />
-          <Input
-            readOnly={disabled}
-            value={lat}
-            type="number"
-            placeholder="请输入纬度"
-            onChange={(e) => setLat(Number(e.target.value))}
-          />
-          {!disabled && (
-            <Button
-              type="primary"
-              onClick={handlePosition.bind(undefined, lng, lat)}
-            >
-              查询
-            </Button>
-          )}
-        </Space>
-
-        <div style={{ width: 650, height: 400 }}>
-          <Amap
-            ref={mapRef}
-            zoom={17}
-            onComplete={handleComplete}
-            onClick={handleClick}
-          >
-            {loaded && position ? (
-              <>
-                <Marker
-                  position={position}
-                  draggable={!disabled}
-                  onDragging={handleMarker}
-                />
-
-                {!disabled && (
-                  <DageMapGeocoder
-                    city={city}
-                    position={position}
-                    onChange={handleGeocoderAddress}
-                  />
-                )}
-              </>
-            ) : (
-              <></>
-            )}
-          </Amap>
-        </div>
-      </>
-    );
-  }
-);
-
-export * from "./types";
-export * from "./utils";

+ 0 - 44
src/components/DageMap/plugins/Geocoder/index.ts

@@ -1,44 +0,0 @@
-import { useAmap, usePlugins } from "@amap/amap-react";
-import { FC, memo, useEffect, useRef } from "react";
-import { AMapGeocoderGetAddressResult } from "../../types";
-
-export interface DageMapGeocoderProps {
-  city?: number | string;
-  position: number[];
-  onChange?: (res: AMapGeocoderGetAddressResult) => void;
-}
-
-export const DageMapGeocoder: FC<DageMapGeocoderProps> = memo(
-  ({ city, position, onChange }) => {
-    const map = useAmap();
-    const AMap = usePlugins(["AMap.Geocoder"]);
-    const geocoder = useRef<any>();
-
-    useEffect(() => {
-      if (!map || !AMap) return;
-      // @ts-ignore
-      geocoder.current = new AMap.Geocoder({
-        city,
-      });
-      map.add(geocoder.current);
-
-      return () => {
-        map.remove(geocoder.current);
-      };
-    }, [map, AMap, city]);
-
-    useEffect(() => {
-      geocoder.current &&
-        geocoder.current.getAddress(
-          position,
-          (status: string, result: AMapGeocoderGetAddressResult) => {
-            if (status === "complete" && result.info === "OK") {
-              onChange?.(result);
-            }
-          }
-        );
-    }, [position, onChange]);
-
-    return null;
-  }
-);

+ 0 - 21
src/components/DageMap/plugins/Geocoder/types.ts

@@ -1,21 +0,0 @@
-export interface AMapGeocoderGetAddressResult {
-  info: string;
-  regeocode: AMapGeocoderGetAddressRegeocode;
-}
-
-export interface AMapGeocoderGetAddressRegeocode {
-  formattedAddress: string;
-  addressComponent: {
-    adcode: string;
-    /** 区 */
-    district: string;
-    /** 市 */
-    province: string;
-    /** 街 */
-    street: string;
-    streetNumber: string;
-    /** 镇 */
-    towncode: string;
-    township: string;
-  };
-}

+ 0 - 1
src/components/DageMap/plugins/index.ts

@@ -1 +0,0 @@
-export * from "./Geocoder";

+ 0 - 35
src/components/DageMap/types.ts

@@ -1,35 +0,0 @@
-export interface DageMapMethods {
-  mapRef: AMap.Map_2 | undefined;
-}
-
-export interface DageMapProps {
-  latitude: number;
-  longitude: number;
-  address: string;
-  disabled?: boolean;
-  /**
-   * 指定进行编码查询的城市,支持传入城市名、adcode 和 citycode
-   */
-  city?: string | number;
-  onChange?(e: DageMapEvent): void;
-  onMapComplete?(): void;
-}
-
-export interface DageMapEvent {
-  lng?: number;
-  lat?: number;
-  address?: string;
-}
-
-export interface DageMapPoisType {
-  adcode: string;
-  address: string;
-  location: string;
-  name: string;
-}
-
-export interface AMapTipsResponse {
-  tips: DageMapPoisType[];
-}
-
-export * from "./plugins/Geocoder/types";

+ 0 - 24
src/components/DageMap/utils.ts

@@ -1,24 +0,0 @@
-import { config as AmapReactConfig } from "@amap/amap-react";
-
-AmapReactConfig.version = "2.0"; // 默认2.0,这里可以不修改
-AmapReactConfig.key = "8de83e1728d5368f8452eee95f35585d";
-
-// @ts-ignore
-window._AMapSecurityConfig = {
-  serviceHost: "https://sit-shgybwg.4dage.com/_AMapService",
-};
-
-/**
- * 修改高德地图 key
- * @param key JS-API key
- * @param serviceHost 安全密钥地址
- */
-export const setAmapJSKey = (key: string, serviceHost?: string) => {
-  AmapReactConfig.key = key;
-  if (serviceHost) {
-    // @ts-ignore
-    window._AMapSecurityConfig = {
-      serviceHost,
-    };
-  }
-};

+ 0 - 6
src/components/DageUpload/index.scss

@@ -1,6 +0,0 @@
-.dage-upload {
-  &__tips {
-    color: #999999;
-    font-size: 12px;
-  }
-}

+ 0 - 184
src/components/DageUpload/index.tsx

@@ -1,184 +0,0 @@
-import { Button, Modal, Upload, message } from "antd";
-import { PlusOutlined } from "@ant-design/icons";
-import { FC, useMemo, useRef, useState } from "react";
-import { RcFile, UploadFile, UploadProps } from "antd/es/upload";
-import { getTokenInfo } from "@/utils";
-import { DageUploadProps, DageUploadType } from "./types";
-import { UploadOutlined } from "@ant-design/icons";
-import "./index.scss";
-
-const getBase64 = (file: RcFile): Promise<string> =>
-  new Promise((resolve, reject) => {
-    const reader = new FileReader();
-    reader.readAsDataURL(file);
-    reader.onload = () => resolve(reader.result as string);
-    reader.onerror = (error) => reject(error);
-  });
-
-export const DageUpload: FC<DageUploadProps> = ({
-  action,
-  value,
-  type = DageUploadType.IMG,
-  maxCount = 9,
-  maxSize = 5,
-  tips,
-  disabled,
-  onUploaded,
-  onUploading,
-  onChange,
-}) => {
-  const [previewOpen, setPreviewOpen] = useState(false);
-  const [previewImage, setPreviewImage] = useState("");
-  const [previewTitle, setPreviewTitle] = useState("");
-  const [uploading, setUploading] = useState(false);
-  const uploadListType = useMemo(() => {
-    switch (type) {
-      case DageUploadType.IMG:
-        return "picture-card";
-      default:
-        return "text";
-    }
-  }, [type]);
-  const isPictureCard = uploadListType === "picture-card";
-  const uploadingFileNum = useRef(0);
-
-  const beforeUpload = (file: RcFile) => {
-    let pass = false;
-    let passFileType = false;
-
-    // 校验文件类型
-    switch (type) {
-      case DageUploadType.IMG:
-        passFileType = ["image/jpeg", "image/png", "image/gif"].includes(
-          file.type
-        );
-        if (!passFileType) {
-          message.error("只支持png、jpg、gif和jpeg格式!");
-        }
-        break;
-      case DageUploadType.MODEL:
-        passFileType = file.name.indexOf(".4dage") > -1;
-        if (!passFileType) {
-          message.error("只支持4dage格式的模型文件!");
-        }
-        break;
-      case DageUploadType.VIDEO:
-        passFileType = ["video/mp4"].includes(file.type);
-        if (!passFileType) {
-          message.error("只支持mp4格式!");
-        }
-        break;
-      case DageUploadType.AUDIO:
-        passFileType = ["audio/mpeg"].includes(file.type);
-        if (!passFileType) {
-          message.error("只支持mp3格式!");
-        }
-        break;
-    }
-
-    // 校验文件大小
-    const isLtM = file.size / 1024 / 1024 < maxSize;
-    if (!isLtM) {
-      message.error(`最大支持 ${maxSize}M!`);
-    }
-
-    uploadingFileNum.current += 1;
-    pass = passFileType && isLtM;
-
-    return pass ? pass : Upload.LIST_IGNORE;
-  };
-
-  const handleChange: UploadProps["onChange"] = ({
-    fileList: newFileList,
-    file,
-  }) => {
-    if (file.status === "uploading") {
-      setUploading(true);
-      onUploading?.();
-    }
-    if (file.status === "done") {
-      uploadingFileNum.current -= 1;
-
-      if (uploading && !uploadingFileNum.current) {
-        setUploading(false);
-        onUploaded?.();
-      }
-    }
-    onChange?.(
-      newFileList.map((i) => ({
-        ...i,
-        dType: type,
-      }))
-    );
-  };
-
-  const handleCancel = () => setPreviewOpen(false);
-
-  const handlePreview = async (file: UploadFile) => {
-    if (!isPictureCard) return;
-
-    if (!file.url && !file.preview) {
-      file.preview = await getBase64(file.originFileObj as RcFile);
-    }
-
-    setPreviewImage(file.url || (file.preview as string));
-    setPreviewOpen(true);
-    setPreviewTitle(
-      file.name || file.url!.substring(file.url!.lastIndexOf("/") + 1)
-    );
-  };
-
-  return (
-    <div className="dage-upload">
-      <Upload
-        disabled={disabled}
-        headers={{
-          token: getTokenInfo().token,
-        }}
-        fileList={value}
-        withCredentials
-        action={process.env.REACT_APP_BACKEND_URL + action}
-        name="file"
-        listType={uploadListType}
-        data={{
-          type,
-        }}
-        maxCount={maxCount}
-        showUploadList={{
-          showDownloadIcon: true,
-        }}
-        multiple={maxCount > 1}
-        onPreview={handlePreview}
-        beforeUpload={beforeUpload}
-        onChange={handleChange}
-      >
-        {!disabled &&
-          (isPictureCard ? (
-            (!value || value.length < maxCount) && <PlusOutlined />
-          ) : (
-            <Button icon={<UploadOutlined />}>上传</Button>
-          ))}
-      </Upload>
-
-      {!!tips && (
-        <p
-          style={{ marginTop: isPictureCard ? 0 : "8px" }}
-          className="dage-upload__tips"
-        >
-          {tips}
-        </p>
-      )}
-
-      <Modal
-        open={previewOpen}
-        title={previewTitle}
-        footer={null}
-        onCancel={handleCancel}
-      >
-        <img alt="example" style={{ width: "100%" }} src={previewImage} />
-      </Modal>
-    </div>
-  );
-};
-
-export * from "./types";

+ 0 - 36
src/components/DageUpload/types.ts

@@ -1,36 +0,0 @@
-import { UploadFile } from "antd";
-
-export enum DageUploadType {
-  /** 缩略图 */
-  THUMB = "thumb",
-  /** 模型 */
-  MODEL = "model",
-  /** 视频 */
-  VIDEO = "video",
-  /** 图片 */
-  IMG = "img",
-  /** 音频 */
-  AUDIO = "audio",
-  /** 文档 */
-  DOC = "doc",
-}
-
-export interface DageFileResponseType extends UploadFile {
-  dType: DageUploadType;
-}
-
-export interface DageUploadProps {
-  action: string;
-  value?: DageFileResponseType[];
-  maxCount?: number;
-  /**
-   * 最大尺寸(M),默认 5M
-   */
-  maxSize?: number;
-  type?: DageUploadType;
-  tips?: string;
-  disabled?: boolean;
-  onUploading?(): void;
-  onUploaded?(): void;
-  onChange?(list: DageFileResponseType[]): void;
-}

+ 0 - 3
src/components/index.ts

@@ -1,5 +1,2 @@
 export * from "./SpinLoding";
-export * from "./DageUpload";
-export * from "./DageMap";
-export * from "./DageFileCheckbox";
 export * from "./FormPageFooter";

+ 5 - 0
src/index.tsx

@@ -2,9 +2,14 @@ import React from "react";
 import ReactDOM from "react-dom/client";
 import { HashRouter } from "react-router-dom";
 import { Provider } from "react-redux";
+import { eventBus } from '@dage/web-components';
 import store from "./store/index";
 import App from "./App";
 
+eventBus.on('Event.login.invalid', () => {
+  globalThis.location.href = '#/login';
+});
+
 const root = ReactDOM.createRoot(
   document.getElementById("root") as HTMLElement
 );

+ 92 - 79
src/pages/History/create-or-edit/index.tsx

@@ -1,5 +1,10 @@
 import { historyApi } from "@/api";
-import { DageUpload, FormPageFooter, MemoSpinLoding } from "@/components";
+import {
+  DageUpload,
+  DageUploadConsumer,
+  DageUploadProvider,
+} from "@dage/web-components";
+import { MemoSpinLoding, FormPageFooter } from "@/components";
 import { HistoryDictItem } from "@/types";
 import { Form, FormInstance, Input, Select } from "antd";
 import { useCallback, useEffect, useRef, useState } from "react";
@@ -12,7 +17,6 @@ export default function HistoryCreateOrEdit() {
   const readonly = useRef(location.pathname.indexOf("view") > -1);
   const formRef = useRef<FormInstance>(null);
   const [loading, setLoading] = useState(false);
-  const [btnDisabled, setBtnDisabled] = useState(false);
   const [dictList, setDictList] = useState<HistoryDictItem[]>([]);
 
   const getDetail = useCallback(async () => {
@@ -55,7 +59,7 @@ export default function HistoryCreateOrEdit() {
     await historyApi.add({
       ...rest,
       fileIds: fileIds
-        .map((i: any) => (!!i.response ? i.response.data.id : i.uid))
+        .map((i: any) => (!!i.response ? i.response.id : i.uid))
         .join(),
     });
 
@@ -73,83 +77,92 @@ export default function HistoryCreateOrEdit() {
   return (
     <div style={{ position: "relative" }}>
       {loading && <MemoSpinLoding />}
-      <Form ref={formRef} labelCol={{ span: 3 }}>
-        <Form.Item
-          label="姓名"
-          name="name"
-          rules={[{ required: true, message: "请输入" }]}
-        >
-          <Input
-            className="w450"
-            placeholder="请输入内容"
-            maxLength={20}
-            showCount
-            readOnly={readonly.current}
-          />
-        </Form.Item>
-        <Form.Item
-          label="所属阶段"
-          name="stage"
-          rules={[{ required: true, message: "请选择" }]}
-        >
-          <Select
-            style={{ width: 200 }}
-            placeholder="请选择"
-            options={dictList.map((i) => ({
-              value: i.name,
-              label: i.name,
-            }))}
-            disabled={readonly.current}
-          />
-        </Form.Item>
-        <Form.Item label="企业" name="companyName">
-          <Input
-            className="w450"
-            placeholder="请输入内容"
-            maxLength={30}
-            showCount
-            readOnly={readonly.current}
-          />
-        </Form.Item>
-        <Form.Item label="简介" name="description">
-          <Input.TextArea
-            className="w450"
-            placeholder="请输入内容"
-            maxLength={200}
-            rows={8}
-            showCount
-            readOnly={readonly.current}
-          />
-        </Form.Item>
-        <Form.Item label="故事" name="story">
-          <Input.TextArea
-            className="w450"
-            placeholder="请输入内容"
-            maxLength={200}
-            rows={8}
-            showCount
-            readOnly={readonly.current}
-          />
-        </Form.Item>
-        <Form.Item label="图片" name="fileIds">
-          <DageUpload
-            disabled={readonly.current}
-            tips="支持png、jpg和jpeg格式;最多9张,最大5M"
-            action="/api/cms/history/upload"
-            onUploading={() => setBtnDisabled(true)}
-            onUploaded={() => setBtnDisabled(false)}
-          />
-        </Form.Item>
-      </Form>
+      <DageUploadProvider>
+        <DageUploadConsumer>
+          {(data) => (
+            <>
+              <Form ref={formRef} labelCol={{ span: 3 }}>
+                <Form.Item
+                  label="姓名"
+                  name="name"
+                  rules={[{ required: true, message: "请输入" }]}
+                >
+                  <Input
+                    className="w450"
+                    placeholder="请输入内容"
+                    maxLength={20}
+                    showCount
+                    readOnly={readonly.current}
+                  />
+                </Form.Item>
+                <Form.Item
+                  label="所属阶段"
+                  name="stage"
+                  rules={[{ required: true, message: "请选择" }]}
+                >
+                  <Select
+                    style={{ width: 200 }}
+                    placeholder="请选择"
+                    options={dictList.map((i) => ({
+                      value: i.name,
+                      label: i.name,
+                    }))}
+                    disabled={readonly.current}
+                  />
+                </Form.Item>
+                <Form.Item label="企业" name="companyName">
+                  <Input
+                    className="w450"
+                    placeholder="请输入内容"
+                    maxLength={30}
+                    showCount
+                    readOnly={readonly.current}
+                  />
+                </Form.Item>
+                <Form.Item label="简介" name="description">
+                  <Input.TextArea
+                    className="w450"
+                    placeholder="请输入内容"
+                    maxLength={200}
+                    rows={8}
+                    showCount
+                    readOnly={readonly.current}
+                  />
+                </Form.Item>
+                <Form.Item label="故事" name="story">
+                  <Input.TextArea
+                    className="w450"
+                    placeholder="请输入内容"
+                    maxLength={200}
+                    rows={8}
+                    showCount
+                    readOnly={readonly.current}
+                  />
+                </Form.Item>
+                <Form.Item label="图片" name="fileIds">
+                  <DageUpload
+                    disabled={readonly.current}
+                    tips="支持png、jpg和jpeg格式;最多9张,最大5M"
+                    action={
+                      process.env.REACT_APP_BACKEND_URL +
+                      "/api/cms/history/upload"
+                    }
+                  />
+                </Form.Item>
+              </Form>
 
-      {!loading && (
-        <FormPageFooter
-          showSubmit={!readonly.current}
-          disabled={btnDisabled}
-          onSubmit={handleSubmit}
-          onCancel={handleCancel}
-        />
-      )}
+              {!loading && (
+                <FormPageFooter
+                  showSubmit={!readonly.current}
+                  disabled={data?.uploading}
+                  onSubmit={handleSubmit}
+                  onCancel={handleCancel}
+                />
+              )}
+            </>
+          )}
+        </DageUploadConsumer>
+      </DageUploadProvider>
     </div>
   );
 }

+ 2 - 2
src/pages/Layout/index.tsx

@@ -15,7 +15,7 @@ import {
   Navigate,
 } from "react-router-dom";
 import { Content } from "antd/es/layout/layout";
-import { hasToken, getTokenInfo } from "@/utils";
+import { hasToken, getTokenInfo } from "@dage/web-components";
 import store from "@/store";
 import { LayoutSider, LayoutHeader } from "./components";
 import { RootState } from "@/store";
@@ -139,7 +139,7 @@ export default function CustomLayout() {
           >
             <Suspense fallback={<MemoSpinLoding />}>
               <Routes>
-                <Route path="/" element={<Navigate to="#/weapon" />} />
+                <Route path="/" element={<Navigate to="/weapon" />} />
                 {menuList.map((menu) => (
                   <Route
                     key={menu.key}

+ 1 - 1
src/pages/Login/index.tsx

@@ -5,7 +5,7 @@ import { useNavigate } from "react-router-dom";
 import encodeStr from "@/utils/pass";
 import { LoginRequest } from "@/types";
 import { login } from "@/api";
-import { setTokenInfo } from "@/utils";
+import { setTokenInfo } from "@dage/web-components";
 import IconAccount from "./images/icon_account.png";
 import IconPassword from "./images/icon_password.png";
 import LogoImage from "../../assets/images/logo.png";

+ 96 - 80
src/pages/Overview/create-or-edit/index.tsx

@@ -4,11 +4,12 @@ import { RangePickerProps } from "antd/es/date-picker";
 import {
   DageMap,
   DageUpload,
-  FormPageFooter,
-  MemoSpinLoding,
   DageMapEvent,
   DageMapMethods,
-} from "@/components";
+  DageUploadProvider,
+  DageUploadConsumer,
+} from "@dage/web-components";
+import { MemoSpinLoding, FormPageFooter } from "@/components";
 import { useCallback, useEffect, useRef, useState } from "react";
 import { useLocation, useNavigate, useParams } from "react-router-dom";
 import { overviewApi } from "@/api";
@@ -25,7 +26,6 @@ export default function OverviewCreateOrEdit() {
   const formRef = useRef<FormInstance>(null);
   const dageMapRef = useRef<DageMapMethods>(null);
   const readonly = useRef(location.pathname.split("/")[2].indexOf("view") > -1);
-  const [btnDisabled, setBtnDisabled] = useState(false);
   const [loading, setLoading] = useState(false);
 
   const [position, setPosition] = useState([121.473581, 31.230536]);
@@ -79,7 +79,7 @@ export default function OverviewCreateOrEdit() {
       longitude: position[0],
       address,
       fileIds: fileIds
-        .map((i: any) => (!!i.response ? i.response.data.id : i.uid))
+        .map((i: any) => (!!i.response ? i.response.id : i.uid))
         .join(),
     });
 
@@ -100,82 +100,98 @@ export default function OverviewCreateOrEdit() {
   return (
     <div className="overview-edit">
       {loading && <MemoSpinLoding />}
-      <Form ref={formRef} initialValues={{ address }} labelCol={{ span: 3 }}>
-        <Form.Item
-          label="企业名称"
-          name="name"
-          rules={[{ required: true, message: "请输入" }]}
-        >
-          <Input
-            readOnly={readonly.current}
-            className="w450"
-            placeholder="请输入内容"
-            maxLength={30}
-            showCount
-          />
-        </Form.Item>
-        <Form.Item label="简介" name="description">
-          <Input.TextArea
-            readOnly={readonly.current}
-            className="w450"
-            placeholder="请输入内容"
-            maxLength={200}
-            showCount
-          />
-        </Form.Item>
-        <Form.Item label="图片" name="fileIds">
-          <DageUpload
-            disabled={readonly.current}
-            tips="支持png、jpg和jpeg格式;最多9张,最大5M"
-            action="/api/cms/history/upload"
-            onUploading={() => setBtnDisabled(true)}
-            onUploaded={() => setBtnDisabled(false)}
-          />
-        </Form.Item>
-        <Form.Item label="企业类型" name="type">
-          <Input
-            readOnly={readonly.current}
-            className="w450"
-            placeholder="请输入内容"
-            maxLength={30}
-            showCount
-          />
-        </Form.Item>
-        <Form.Item
-          label="成立日期"
-          name="createDay"
-          rules={[{ required: true, message: "请选择" }]}
-        >
-          <DatePicker
-            disabled={readonly.current}
-            className="w450"
-            format="YYYY-MM-DD"
-            disabledDate={disabledDate}
-          />
-        </Form.Item>
-        <Form.Item
-          label="地址"
-          name="address"
-          rules={[{ required: true, message: "请选择" }]}
-        >
-          <DageMap
-            disabled={readonly.current}
-            ref={dageMapRef}
-            longitude={position[0]}
-            latitude={position[1]}
-            address={address}
-            city={310000}
-            onChange={handleMapChange}
-          />
-        </Form.Item>
-      </Form>
+      <DageUploadProvider>
+        <DageUploadConsumer>
+          {(data) => {
+            return (
+              <>
+                <Form
+                  ref={formRef}
+                  initialValues={{ address }}
+                  labelCol={{ span: 3 }}
+                >
+                  <Form.Item
+                    label="企业名称"
+                    name="name"
+                    rules={[{ required: true, message: "请输入" }]}
+                  >
+                    <Input
+                      readOnly={readonly.current}
+                      className="w450"
+                      placeholder="请输入内容"
+                      maxLength={30}
+                      showCount
+                    />
+                  </Form.Item>
+                  <Form.Item label="简介" name="description">
+                    <Input.TextArea
+                      readOnly={readonly.current}
+                      className="w450"
+                      placeholder="请输入内容"
+                      maxLength={200}
+                      showCount
+                    />
+                  </Form.Item>
+                  <Form.Item label="图片" name="fileIds">
+                    <DageUpload
+                      disabled={readonly.current}
+                      tips="支持png、jpg和jpeg格式;最多9张,最大5M"
+                      action={
+                        process.env.REACT_APP_BACKEND_URL +
+                        "/api/cms/history/upload"
+                      }
+                    />
+                  </Form.Item>
+                  <Form.Item label="企业类型" name="type">
+                    <Input
+                      readOnly={readonly.current}
+                      className="w450"
+                      placeholder="请输入内容"
+                      maxLength={30}
+                      showCount
+                    />
+                  </Form.Item>
+                  <Form.Item
+                    label="成立日期"
+                    name="createDay"
+                    rules={[{ required: true, message: "请选择" }]}
+                  >
+                    <DatePicker
+                      disabled={readonly.current}
+                      className="w450"
+                      format="YYYY-MM-DD"
+                      disabledDate={disabledDate}
+                    />
+                  </Form.Item>
+                  <Form.Item
+                    label="地址"
+                    name="address"
+                    rules={[{ required: true, message: "请选择" }]}
+                  >
+                    <DageMap
+                      disabled={readonly.current}
+                      ref={dageMapRef}
+                      longitude={position[0]}
+                      latitude={position[1]}
+                      address={address}
+                      city={310000}
+                      inputTipsApi="/api/cms/goods/mapSearch/"
+                      onChange={handleMapChange}
+                    />
+                  </Form.Item>
+                </Form>
 
-      <FormPageFooter
-        showSubmit={!readonly.current}
-        disabled={btnDisabled}
-        onSubmit={handleSubmit}
-        onCancel={handleCancel}
-      />
+                <FormPageFooter
+                  showSubmit={!readonly.current}
+                  disabled={data?.uploading}
+                  onSubmit={handleSubmit}
+                  onCancel={handleCancel}
+                />
+              </>
+            );
+          }}
+        </DageUploadConsumer>
+      </DageUploadProvider>
     </div>
   );
 }

+ 152 - 146
src/pages/Weapon/create-or-edit/index.tsx

@@ -1,12 +1,13 @@
 import { weaponApi } from "@/api";
+import { FormPageFooter, MemoSpinLoding } from "@/components";
 import {
   DageFileCheckbox,
   DageFileCheckboxMethods,
   DageFileResponseType,
   DageUpload,
-  FormPageFooter,
-  MemoSpinLoding,
-} from "@/components";
+  DageUploadConsumer,
+  DageUploadProvider,
+} from "@dage/web-components";
 import { HistoryDictItem } from "@/types";
 import { Form, FormInstance, Input, Select } from "antd";
 import { useCallback, useEffect, useRef, useState } from "react";
@@ -20,7 +21,6 @@ export default function HistoryCreateOrEdit() {
   const formRef = useRef<FormInstance>(null);
   const dageFileCheckboxRef = useRef<DageFileCheckboxMethods>(null);
   const [loading, setLoading] = useState(false);
-  const [btnDisabled, setBtnDisabled] = useState(false);
   const [dictList, setDictList] = useState<HistoryDictItem[]>([]);
   const [fileList, setFileList] = useState<DageFileResponseType[]>([]);
 
@@ -85,7 +85,7 @@ export default function HistoryCreateOrEdit() {
         .map((i: any) => (!!i.response ? i.response.data.filePath : i.uid))
         .join(),
       fileIds: fileList
-        .map((i) => (!!i.response ? i.response.data.id : i.uid))
+        .map((i) => (!!i.response ? i.response.id : i.uid))
         .join(),
     });
 
@@ -107,148 +107,154 @@ export default function HistoryCreateOrEdit() {
   return (
     <div style={{ position: "relative" }}>
       {loading && <MemoSpinLoding />}
-      <Form ref={formRef} labelCol={{ span: 3 }}>
-        <Form.Item
-          label="名称"
-          name="name"
-          rules={[{ required: true, message: "请输入" }]}
-        >
-          <Input
-            className="w450"
-            placeholder="请输入内容"
-            maxLength={20}
-            showCount
-            readOnly={readonly.current}
-          />
-        </Form.Item>
-        <Form.Item
-          label="所属阶段"
-          name="stage"
-          rules={[{ required: true, message: "请选择" }]}
-        >
-          <Select
-            style={{ width: 200 }}
-            placeholder="请选择"
-            options={dictList.map((i) => ({
-              value: i.name,
-              label: i.name,
-            }))}
-            disabled={readonly.current}
-          />
-        </Form.Item>
-        <Form.Item label="行业" name="vocation">
-          <Input
-            className="w450"
-            placeholder="请输入内容"
-            maxLength={30}
-            showCount
-            readOnly={readonly.current}
-          />
-        </Form.Item>
-        <Form.Item label="类型" name="type">
-          <Input
-            className="w450"
-            placeholder="请输入内容"
-            maxLength={30}
-            showCount
-            readOnly={readonly.current}
-          />
-        </Form.Item>
-        <Form.Item label="生产厂家" name="company">
-          <Input
-            className="w450"
-            placeholder="请输入内容"
-            maxLength={30}
-            showCount
-            readOnly={readonly.current}
-          />
-        </Form.Item>
-        <Form.Item label="年份" name="year">
-          <Input
-            className="w450"
-            placeholder="请输入内容"
-            maxLength={30}
-            showCount
-            readOnly={readonly.current}
-          />
-        </Form.Item>
-        <Form.Item label="尺寸" name="size">
-          <Input
-            className="w450"
-            placeholder="请输入内容"
-            maxLength={30}
-            showCount
-            readOnly={readonly.current}
-          />
-        </Form.Item>
-        <Form.Item label="重量" name="weight">
-          <Input
-            className="w450"
-            placeholder="请输入内容"
-            maxLength={30}
-            showCount
-            readOnly={readonly.current}
-          />
-        </Form.Item>
-        <Form.Item label="简介" name="description">
-          <Input.TextArea
-            className="w450"
-            placeholder="请输入内容"
-            maxLength={200}
-            rows={8}
-            showCount
-            readOnly={readonly.current}
-          />
-        </Form.Item>
-        <Form.Item label="选送理由" name="reason">
-          <Input.TextArea
-            className="w450"
-            placeholder="请输入内容"
-            maxLength={200}
-            rows={4}
-            showCount
-            readOnly={readonly.current}
-          />
-        </Form.Item>
-        <Form.Item
-          label="封面图"
-          name="thumb"
-          rules={[{ required: true, message: "请输入" }]}
-        >
-          <DageUpload
-            maxCount={1}
-            disabled={readonly.current}
-            tips="支持png、jpg和jpeg格式;最大20M,最多1张"
-            action="/api/cms/goods/upload"
-            onUploading={() => setBtnDisabled(true)}
-            onUploaded={() => setBtnDisabled(false)}
-          />
-        </Form.Item>
-        <Form.Item
-          label="文件类型"
-          name="fileTypes"
-          rules={[
-            { required: true, message: "请选择" },
-            { validator: dageFileCheckboxRef.current?.validate! },
-          ]}
-        >
-          <DageFileCheckbox
-            ref={dageFileCheckboxRef}
-            disabled={readonly.current}
-            action="/api/cms/goods/upload"
-            onFileChange={handleFileChange}
-          />
-        </Form.Item>
-      </Form>
+      <DageUploadProvider>
+        <DageUploadConsumer>
+          {(data) => (
+            <>
+              <Form ref={formRef} labelCol={{ span: 3 }}>
+                <Form.Item
+                  label="名称"
+                  name="name"
+                  rules={[{ required: true, message: "请输入" }]}
+                >
+                  <Input
+                    className="w450"
+                    placeholder="请输入内容"
+                    maxLength={20}
+                    showCount
+                    readOnly={readonly.current}
+                  />
+                </Form.Item>
+                <Form.Item
+                  label="所属阶段"
+                  name="stage"
+                  rules={[{ required: true, message: "请选择" }]}
+                >
+                  <Select
+                    style={{ width: 200 }}
+                    placeholder="请选择"
+                    options={dictList.map((i) => ({
+                      value: i.name,
+                      label: i.name,
+                    }))}
+                    disabled={readonly.current}
+                  />
+                </Form.Item>
+                <Form.Item label="行业" name="vocation">
+                  <Input
+                    className="w450"
+                    placeholder="请输入内容"
+                    maxLength={30}
+                    showCount
+                    readOnly={readonly.current}
+                  />
+                </Form.Item>
+                <Form.Item label="类型" name="type">
+                  <Input
+                    className="w450"
+                    placeholder="请输入内容"
+                    maxLength={30}
+                    showCount
+                    readOnly={readonly.current}
+                  />
+                </Form.Item>
+                <Form.Item label="生产厂家" name="company">
+                  <Input
+                    className="w450"
+                    placeholder="请输入内容"
+                    maxLength={30}
+                    showCount
+                    readOnly={readonly.current}
+                  />
+                </Form.Item>
+                <Form.Item label="年份" name="year">
+                  <Input
+                    className="w450"
+                    placeholder="请输入内容"
+                    maxLength={30}
+                    showCount
+                    readOnly={readonly.current}
+                  />
+                </Form.Item>
+                <Form.Item label="尺寸" name="size">
+                  <Input
+                    className="w450"
+                    placeholder="请输入内容"
+                    maxLength={30}
+                    showCount
+                    readOnly={readonly.current}
+                  />
+                </Form.Item>
+                <Form.Item label="重量" name="weight">
+                  <Input
+                    className="w450"
+                    placeholder="请输入内容"
+                    maxLength={30}
+                    showCount
+                    readOnly={readonly.current}
+                  />
+                </Form.Item>
+                <Form.Item label="简介" name="description">
+                  <Input.TextArea
+                    className="w450"
+                    placeholder="请输入内容"
+                    maxLength={200}
+                    rows={8}
+                    showCount
+                    readOnly={readonly.current}
+                  />
+                </Form.Item>
+                <Form.Item label="选送理由" name="reason">
+                  <Input.TextArea
+                    className="w450"
+                    placeholder="请输入内容"
+                    maxLength={200}
+                    rows={4}
+                    showCount
+                    readOnly={readonly.current}
+                  />
+                </Form.Item>
+                <Form.Item
+                  label="封面图"
+                  name="thumb"
+                  rules={[{ required: true, message: "请输入" }]}
+                >
+                  <DageUpload
+                    maxCount={1}
+                    disabled={readonly.current}
+                    tips="支持png、jpg和jpeg格式;最大20M,最多1张"
+                    action="/api/cms/goods/upload"
+                  />
+                </Form.Item>
+                <Form.Item
+                  label="文件类型"
+                  name="fileTypes"
+                  rules={[
+                    { required: true, message: "请选择" },
+                    { validator: dageFileCheckboxRef.current?.validate! },
+                  ]}
+                >
+                  <DageFileCheckbox
+                    ref={dageFileCheckboxRef}
+                    disabled={readonly.current}
+                    action="/api/cms/goods/upload"
+                    onFileChange={handleFileChange}
+                  />
+                </Form.Item>
+              </Form>
 
-      {!loading && (
-        <FormPageFooter
-          showSubmit={!readonly.current}
-          disabled={btnDisabled}
-          onSubmit={handleSubmit}
-          onCancel={handleCancel}
-        />
-      )}
+              {!loading && (
+                <FormPageFooter
+                  showSubmit={!readonly.current}
+                  disabled={data?.uploading}
+                  onSubmit={handleSubmit}
+                  onCancel={handleCancel}
+                />
+              )}
+            </>
+          )}
+        </DageUploadConsumer>
+      </DageUploadProvider>
     </div>
   );
 }

+ 1 - 3
src/utils/index.ts

@@ -1,8 +1,6 @@
-import { removeTokenInfo } from "./storage";
+import { removeTokenInfo } from "@dage/web-components";
 import { logoutApi } from "@/api";
 
-export * from "./storage";
-
 export const logout = async () => {
   await logoutApi();
 

+ 0 - 145
src/utils/services.ts

@@ -1,145 +0,0 @@
-import { message } from "antd";
-import { NoticeType } from "antd/es/message/interface";
-import axios, {
-  type AxiosInstance,
-  type InternalAxiosRequestConfig,
-  type AxiosResponse,
-} from "axios";
-import isNumber from "lodash/isNumber";
-import { getTokenInfo } from "./storage";
-
-export enum ResponseStatusCode {
-  SUCCESS = 0,
-  TOKEN_INVALID = 5001,
-  TOKEN_INVALID2 = 5002,
-}
-
-interface Config<D = any> extends InternalAxiosRequestConfig<D> {
-  /**
-   * 隐藏错误提醒
-   */
-  hidden?: boolean;
-}
-
-export interface DageResponse<T = any, D = any> extends AxiosResponse<T, D> {
-  code: number;
-  msg: string;
-  success: boolean;
-}
-
-interface Service extends AxiosInstance {
-  get<T = any, R = DageResponse<T>, D = any>(
-    url: string,
-    config?: Config<D>
-  ): Promise<R>;
-  post<T = any, R = DageResponse<T>, D = any>(
-    url: string,
-    data?: D,
-    config?: Config<D>
-  ): Promise<R>;
-}
-
-const service: Service = axios.create({
-  baseURL: process.env.REACT_APP_BACKEND_URL,
-  timeout: 60000,
-  headers: {
-    "Cache-Control": "no-cache",
-    "Content-Type": "application/json;charset=UTF-8",
-    "X-Requested-With": "XMLHttpRequest",
-  },
-});
-
-/**
- * 服务端接口empty字符串跟null返回的结果不同,过滤掉empty字符串
- * @param params
- * @param emptyString 是否过滤空字符串
- */
-function filterEmptyKey(params: any, emptyString = false) {
-  if (Array.isArray(params) || params == null) {
-    return params;
-  }
-
-  Object.keys(params).forEach((key) => {
-    if (params[key] === null || (emptyString && params[key] === "")) {
-      delete params[key];
-    }
-  });
-}
-
-const showMessage = (msg: string, type: NoticeType = "error") => {
-  message.open({
-    type,
-    content: msg,
-    duration: 4,
-  });
-};
-
-service.interceptors.request.use((config: Config) => {
-  const { token } = getTokenInfo();
-  if (token) config.headers.token = token;
-
-  if (config.method === "post") {
-    const params = {
-      ...config.data,
-    };
-    filterEmptyKey(params); // 过滤空字符串
-    config.data = params;
-  } else if (config.method === "get") {
-    config.params = {
-      _t: new Date().getTime() / 1000,
-      ...config.params,
-    };
-    filterEmptyKey(config.params, true);
-  }
-  return config;
-});
-
-service.interceptors.response.use(
-  (res) => {
-    const { data, config }: { config: Config; data: DageResponse } = res;
-
-    // data 有可能直接返回数据
-    if (isNumber(data.code)) {
-      if (
-        [
-          ResponseStatusCode.TOKEN_INVALID,
-          ResponseStatusCode.TOKEN_INVALID2,
-        ].includes(data.code)
-      ) {
-        const msg = "登录失效!";
-        showMessage(msg);
-        globalThis.location.href = "/login";
-
-        return Promise.reject({
-          code: data.code,
-          msg,
-        });
-      } else if (data.code !== ResponseStatusCode.SUCCESS) {
-        const msg = data.msg || "加载失败";
-        const code = data.code || -1000;
-
-        // 未手动配置 隐藏 消息提示时,公共提醒错误
-        if (!config.hidden) {
-          setTimeout(() => {
-            showMessage(msg);
-          }, 0);
-        }
-
-        return Promise.reject({
-          code,
-          msg,
-        });
-      }
-    }
-
-    return data || {};
-  },
-  (error) => {
-    showMessage(error.message);
-    return new Promise((res, rej) => {
-      rej(error);
-    });
-  }
-);
-
-export default service as Required<Service>;

+ 0 - 33
src/utils/storage.ts

@@ -1,33 +0,0 @@
-// ------------------------------------token的本地存储------------------------------------
-
-// 用户 Token 的本地缓存键名,自己定义
-const TOKEN_KEY = "SH_GBG_USER_INFO";
-
-/**
- * 从本地缓存中获取 Token 信息
- */
-export const getTokenInfo = (): any => {
-  return JSON.parse(localStorage.getItem(TOKEN_KEY) || "{}");
-};
-
-/**
- * 将 Token 信息存入缓存
- * @param {Object} tokenInfo 从后端获取到的 Token 信息
- */
-export const setTokenInfo = (tokenInfo: any): void => {
-  localStorage.setItem(TOKEN_KEY, JSON.stringify(tokenInfo));
-};
-
-/**
- * 删除本地缓存中的 Token 信息
- */
-export const removeTokenInfo = (): void => {
-  localStorage.removeItem(TOKEN_KEY);
-};
-
-/**
- * 判断本地缓存中是否存在 Token 信息
- */
-export const hasToken = (): boolean => {
-  return Boolean(getTokenInfo().token);
-};

Datei-Diff unterdrückt, da er zu groß ist
+ 729 - 309
yarn.lock