最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

React表單容器的通用解決方案

 更新時(shí)間:2022年04月24日 09:27:22   作者:Pwcong  
本文主要介紹了React表單容器的通用解決方案,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

1. 前話

提問(wèn):ToB中臺(tái)類系統(tǒng)的后端開(kāi)發(fā)主要做啥?

??‍♂?:CRUD

再次提問(wèn):那前端開(kāi)發(fā)呢?

??‍♂?:增刪查改

開(kāi)個(gè)玩笑哈啊哈哈哈??????

雖然沒(méi)有具體數(shù)據(jù)統(tǒng)計(jì),但作者仍主觀地認(rèn)為中臺(tái)類的系統(tǒng)的前端內(nèi)容至少一半都是增刪查改??????,其對(duì)應(yīng)的前端頁(yè)面類型就是列表頁(yè)面和表單頁(yè)面。

對(duì)于列表頁(yè)面的通用實(shí)現(xiàn),如果讀者有看過(guò)《React通用解決方案——組件數(shù)據(jù)請(qǐng)求》一文應(yīng)該會(huì)根據(jù)自身實(shí)際業(yè)務(wù)場(chǎng)景得出較好的解決方案,提升實(shí)際業(yè)務(wù)的列表頁(yè)面的開(kāi)發(fā)效率。

而對(duì)于表單頁(yè)面,又該如何實(shí)現(xiàn)以作為通用開(kāi)發(fā)模版進(jìn)行提效?大致有兩種:

  • 一種「配置表單」,也就是定義表單DSL,通過(guò)JSON配置生成表單頁(yè)面,這也是業(yè)界低代碼平臺(tái)的表單實(shí)現(xiàn)。優(yōu)點(diǎn)是顯而易見(jiàn)的,配置簡(jiǎn)單,快速實(shí)現(xiàn)。缺點(diǎn)是靈活性受限于DSL的完整性,對(duì)于特殊場(chǎng)景需進(jìn)行表單組件底層實(shí)現(xiàn)的定制化。
  • 另一種是「原生表單」,也就是直接使用表單組件。其優(yōu)缺陷大致與「配置表單」相反。

本篇由于主題定義就不講解表單的通用實(shí)現(xiàn)只分享表單的通用呈現(xiàn)哈??‍♂???‍♂???‍♂?下面開(kāi)始正文。

2. 正文

常見(jiàn)的表單的呈現(xiàn)有兩種模式,分別是頁(yè)面和浮層。

首先是「頁(yè)面表單」,也就是以頁(yè)面的形式呈現(xiàn)表單。示例代碼如下:

const FormPage: React.FC = () => {
  const [form] = useForm();

  const handleSubmit = useCallback((value) => {
    // TODO 表單提交邏輯
    console.log(value);
  }, []);

  return (
    <div className="test-page">
      <h2>新建用戶</h2>
      <Form form={form} onSubmit={handleSubmit} layout="inline">
        <Form.Item
          field="name"
          label="名稱"
          rules={[
            {
              required: true,
              message: "請(qǐng)輸入名稱",
            },
          ]}
        >
          <Input placeholder="請(qǐng)輸入" />
        </Form.Item>
        <Form.Item>
          <Button htmlType="submit">提交</Button>
        </Form.Item>
      </Form>
    </div>
  );
};

瀏覽器展現(xiàn)如下:

某一天,產(chǎn)品為了優(yōu)化交互體驗(yàn)改成「以彈窗呈現(xiàn)表單」,這時(shí)便會(huì)用到表單的另一種呈現(xiàn)——「浮層表單」。在原「頁(yè)面表單」的實(shí)現(xiàn)中進(jìn)行修改,修改后的示例代碼如下:

const FormPage: React.FC = () => {
  const [form] = useForm();

  const visible = useBoolean(false);

  const handleSubmit = useCallback(() => {
    form.validate((error, value) => {
      if (error) {
        return;
      }
      // TODO 表單提交邏輯
      console.log(value);

      visible.setFalse();
    });
  }, []);

  return (
    <div className="test-page">
      <h2>新建用戶</h2>
      <Button onClick={visible.setTrue}>點(diǎn)擊新建</Button>

      <Modal
        visible={visible.state}
        title="新建用戶"
        okText="提交"
        onOk={handleSubmit}
        onCancel={visible.setFalse}
      >
        <Form form={form} layout="inline">
          <Form.Item
            field="name"
            label="名稱"
            rules={[
              {
                required: true,
                message: "請(qǐng)輸入名稱",
              },
            ]}
          >
            <Input placeholder="請(qǐng)輸入" />
          </Form.Item>
        </Form>
      </Modal>
    </div>
  );
};

瀏覽器展現(xiàn)如下:

某一天,產(chǎn)品提了個(gè)新需求,另一個(gè)「用戶新建頁(yè)面表單」。某一天,產(chǎn)品提了個(gè)新需求,另一個(gè)「用戶新建彈窗表單」。某一天,產(chǎn)品提了個(gè)新需求,另一個(gè)「用戶新建抽屜表單」。某一天。。。

這時(shí)RD糾結(jié)了,為了快速完成需求直接是拷貝一個(gè)新的「FormPage」組件完成交付最終的結(jié)局肯定就是「禿頭」,亟需總結(jié)個(gè)通用的解決方案應(yīng)對(duì)表單不同呈現(xiàn)的場(chǎng)景的實(shí)現(xiàn)。

切入點(diǎn)是對(duì)表單和呈現(xiàn)進(jìn)行拆分,避免表單和呈現(xiàn)的耦合。

那該如何拆分?我們先明確下表單和呈現(xiàn)各自的關(guān)注點(diǎn),表單主要關(guān)注表單值和表單動(dòng)作,而呈現(xiàn)主要關(guān)注自身的樣式。如果表單的動(dòng)作需要呈現(xiàn)進(jìn)行觸發(fā),例如彈窗的確定按鈕觸發(fā)表單的提交動(dòng)作呢?這就需要表單與呈現(xiàn)之間需存在連接的橋梁。

作者根據(jù)這個(gè)思路最終拆分的結(jié)果是,實(shí)現(xiàn)了個(gè)「表單容器」?!副韱巍?「表單容器」,讓表單的實(shí)現(xiàn)不關(guān)注呈現(xiàn),從而實(shí)現(xiàn)表單的復(fù)用,提升了開(kāi)發(fā)效率。

2.1 表單容器定義

表單容器的定義基于浮層容器拓展,定義如下:

  • 表單容器支持各種呈現(xiàn)(彈窗和抽屜等);
  • 表單容器只關(guān)注浮層的標(biāo)題、顯隱狀態(tài)和顯隱狀態(tài)變更處理邏輯,不關(guān)注浮層內(nèi)容;
  • 表單容器組件提供接口控制浮層容器的標(biāo)題和顯隱狀態(tài);
  • 任何內(nèi)容被表單容器包裹即可獲得浮層的能力;
  • 表單容器提供向浮層內(nèi)容透?jìng)鲗傩缘哪芰Γ瑑?nèi)置透?jìng)鱂orm實(shí)例、表單模式和只讀狀態(tài)的屬性;
  • 表單容器的浮層確認(rèn)邏輯自動(dòng)觸發(fā)Form實(shí)例的提交邏輯

基于上面的定義實(shí)現(xiàn)的TS類型定義如下:

import React from "react";

import { ModalProps, DrawerProps, FormInstance } from "@arco-design/web-react";

import { EFormMode, IBaseFormProps } from "@/hooks/use-common-form";

export type IFormWrapperBaseProps = {
  /** 標(biāo)題 */
  title?: React.ReactNode;
};

export type IFormWrapperOpenProps<T = any, P = {}> = IFormWrapperBaseProps & {
  /** 表單模式 */
  mode?: EFormMode;
  /** 表單值 */
  value?: T;
  /** 內(nèi)容屬性 */
  props?: P;
};

export type IFormWrapperProps<T = any, P = {}> = IFormWrapperBaseProps & {
  /** 表單彈窗提交回調(diào)函數(shù) */
  onSubmit?: (
    /** 提交表單值 */
    formValue: T,
    /** 當(dāng)前表單值 */
    currentValue: T,
    /** 表單模式 */
    formMode: EFormMode,
    /** 內(nèi)容屬性 */
    componentProps?: P
  ) => Promise<void>;
  /** 表單彈窗提交回調(diào)函數(shù) */
  onOk?: (result: any, componentProps?: P) => void | Promise<void>;
  /** 表單彈窗提交回調(diào)函數(shù) */
  onCancel?: () => void;
  /** 內(nèi)容屬性 */
  componentProps?: P;
};

export type IFormWrappedModalProps<T = any, P = {}> = Omit<
  ModalProps,
  "onOk" | "onCancel"
> &
  IFormWrapperProps<T, P>;

export type IFormWrappedDrawerProps<T = any, P = {}> = Omit<
  DrawerProps,
  "onOk" | "onCancel"
> &
  IFormWrapperProps<T, P> & {
    operation?: React.ReactNode;
  };

export type IFormWrapperRef<T = any, P = {}> = {
  /** 表單彈窗打開(kāi)接口 */
  open: (openProps?: IFormWrapperOpenProps<T, P>) => void;
  /** 表單彈窗關(guān)閉接口 */
  close: () => void;
};

export type IWithFormWrapperOptions<T = any, P = {}> = {
  /** 默認(rèn)值 */
  defaultValue: T;
  /** 默認(rèn)屬性 */
  defaultProps?: Partial<IFormWrapperProps<T, P>>;
};

export type IWithFormWrapperProps<T = any, P = {}> = IBaseFormProps & {
  /** 表單實(shí)例 */
  form: FormInstance<T>;
} & P;

2.2 表單容器定義實(shí)現(xiàn)

基于上面的表單容器定義,我們這里實(shí)現(xiàn)一個(gè)Hook,實(shí)現(xiàn)代碼如下:

/**
 * 表單容器Hook
 * @param ref 浮層實(shí)例
 * @param wrapperProps 浮層屬性
 * @param defaultValue 默認(rèn)值
 * @returns
 */
export function useFormWrapper<T = any, P = {}>(
  ref: ForwardedRef<IFormWrapperRef<T, P>>,
  wrapperProps: IFormWrapperProps<T, P>,
  defaultValue: T,
) {
  const [form] = Form.useForm();

  const visible = useBoolean(false);
  const loading = useBoolean(false);

  const [title, setTitle] = useState<React.ReactNode>();
  const [componentProps, setComponentProps] = useState<P>();

  const [value, setValue] = useState(defaultValue);
  const [mode, setMode] = useState(EFormMode.view);

  // 計(jì)算是否只讀
  const readOnly = useReadOnly(mode);

  // 提交處理邏輯
  const onOk = async () => {
    loading.setTrue();

    const targetComponentProps = wrapperProps.componentProps ?? componentProps;

    try {
      // 校驗(yàn)表單
      const formValue = await form.validate();
      // 提交表單
      const result = await wrapperProps?.onSubmit?.(
        formValue,
        value,
        mode,
        targetComponentProps,
      );
      await wrapperProps.onOk?.(result, targetComponentProps);
      visible.setFalse();
    } catch (err) {
      console.error(err);
    } finally {
      loading.setFalse();
    }
  };

  // 取消處理邏輯
  const onCancel = () => {
    wrapperProps.onCancel?.();
    visible.setFalse();
  };

  // 實(shí)例掛載表單操作接口
  useImperativeHandle(
    ref,
    (): IFormWrapperRef<T, P> => ({
      open: openProps => {
        const {
          title: newTitle,
          mode: newMode = EFormMode.view,
          value: newValue = defaultValue,
        } = openProps ?? {};

        setMode(newMode);
        setTitle(newTitle);
        setValue(newValue);

        form.resetFields();
        form.setFieldsValue(newValue);
        visible.setTrue();
      },
      close: onCancel,
    }),
  );

  // 初始化表單默認(rèn)值
  useEffect(() => {
    form.setFieldsValue(defaultValue);
  }, []);

  const ret = [
    {
      visible,
      loading,
      title,
      componentProps,
      form,
      value,
      mode,
      readOnly,
    },
    {
      onOk,
      onCancel,
      setTitle,
      setComponentProps,
      setValue,
      setMode,
    },
  ] as const;

  return ret;
}

2.3 表單容器呈現(xiàn)實(shí)現(xiàn)

表單容器的呈現(xiàn)有多種,常見(jiàn)的為彈窗和抽屜。下面我使用Arco對(duì)應(yīng)組件進(jìn)行呈現(xiàn)實(shí)現(xiàn) ?? 。

2.3.1 彈窗表單容器

/**
 * 表單彈窗容器
 * @param options 表單配置
 * @returns
 */
function withModal<T = any, P = {}>(options: IWithFormWrapperOptions<T, P>) {
  const { defaultValue, defaultProps } = options;

  return function (Component: any) {
    const WrappedComponent = (
      props: IFormWrappedModalProps<T, P>,
      ref: ForwardedRef<IFormWrapperRef<T, P>>,
    ) => {
      const wrapperProps = {
        ...defaultProps,
        ...props,
      };

      const {
        componentProps,
        title,
        visible,
        okButtonProps,
        cancelButtonProps,
        okText = 'Submit',
        cancelText = 'Cancel',
        maskClosable = false,
        unmountOnExit = true,
        ...restProps
      } = wrapperProps;

      const [
        {
          form,
          mode,
          readOnly,
          visible: currentVisible,
          title: currentTitle,
          componentProps: currentComponentProps,
        },
        { onOk, onCancel },
      ] = useFormWrapper<T, P>(ref, wrapperProps, defaultValue);

      return (
        <Modal
          {...restProps}
          maskClosable={maskClosable}
          visible={visible ?? currentVisible.state}
          onOk={onOk}
          okText={okText}
          okButtonProps={{
            hidden: readOnly,
            ...okButtonProps,
          }}
          onCancel={onCancel}
          cancelText={cancelText}
          cancelButtonProps={{
            hidden: readOnly,
            ...cancelButtonProps,
          }}
          title={title ?? currentTitle}
          unmountOnExit={unmountOnExit}>
          {React.createElement(Component, {
            form,
            mode,
            readOnly,
            ...(componentProps ?? currentComponentProps),
          })}
        </Modal>
      );
    };

    WrappedComponent.displayName = `FormWrapper.withModal(${getDisplayName(
      Component,
    )})`;

    const ForwardedComponent = forwardRef<
      IFormWrapperRef<T, P>,
      IFormWrappedModalProps<T, P>
    >(WrappedComponent);

    return ForwardedComponent;
  };
}

2.3.1 抽屜表單容器

/**
 * 表單抽屜容器
 * @param options 表單配置
 * @returns
 */
function withDrawer<T = any, P = {}>(options: IWithFormWrapperOptions<T, P>) {
  const { defaultValue, defaultProps } = options;

  return function (Component: any) {
    const WrappedComponent = (
      props: IFormWrappedDrawerProps<T, P>,
      ref: ForwardedRef<IFormWrapperRef<T, P>>,
    ) => {
      const wrapperProps = {
        ...defaultProps,
        ...props,
      };

      const {
        title,
        visible,
        componentProps,
        okText = 'Submit',
        okButtonProps,
        cancelText = 'Cancel',
        cancelButtonProps,
        maskClosable = false,
        unmountOnExit = true,
        operation,
        ...restProps
      } = wrapperProps;

      const [
        {
          form,
          mode,
          readOnly,
          loading,
          visible: currentVisible,
          title: currentTitle,
          componentProps: currentComponentProps,
        },
        { onOk, onCancel },
      ] = useFormWrapper<T, P>(ref, wrapperProps, defaultValue);

      const footerNode = useMemo(
        () => (
          <div style={{ textAlign: 'right' }}>
            {operation}

            {!readOnly && (
              <>
                <Button
                  type="default"
                  onClick={onCancel}
                  {...cancelButtonProps}>
                  {cancelText}
                </Button>
                <Button
                  type="primary"
                  loading={loading.state}
                  onClick={onOk}
                  style={{ marginLeft: '8px' }}
                  {...okButtonProps}>
                  {okText}
                </Button>
              </>
            )}
          </div>
        ),
        [
          loading.state,
          onOk,
          onCancel,
          okText,
          cancelText,
          readOnly,
          okButtonProps,
          cancelButtonProps,
        ],
      );

      const showFooter = useMemo(
        () => !(readOnly && !operation),
        [readOnly, operation],
      );

      return (
        <Drawer
          {...restProps}
          maskClosable={maskClosable}
          visible={visible ?? currentVisible.state}
          title={title ?? currentTitle}
          footer={showFooter ? footerNode : null}
          unmountOnExit={unmountOnExit}
          onCancel={onCancel}>
          {React.createElement(Component, {
            form,
            mode,
            readOnly,
            ...(componentProps ?? currentComponentProps),
          })}
        </Drawer>
      );
    };

    WrappedComponent.displayName = `FormWrapper.withDrawer(${getDisplayName(
      Component,
    )})`;

    const ForwardedComponent = forwardRef<
      IFormWrapperRef<T, P>,
      IFormWrappedDrawerProps<T, P>
    >(WrappedComponent);

    return ForwardedComponent;
  };
}

2.4 表單容器用例

對(duì)于上面的代碼示例我們進(jìn)行以下改造,將頁(yè)面的表單抽離成單獨(dú)的表單組件,代碼如下:

type IUserFormValue = {
  name?: string;
};

const UserForm: React.FC<IWithFormWrapperProps<IUserFormValue>> = ({
  form,
}) => {
  return (
    <Form form={form} layout="inline">
      <Form.Item
        field="name"
        label="名稱"
        rules={[
          {
            required: true,
            message: "請(qǐng)輸入名稱",
          },
        ]}
      >
        <Input placeholder="請(qǐng)輸入" />
      </Form.Item>
    </Form>
  );
};

下面我們就可以使用上面實(shí)現(xiàn)的表單容器進(jìn)行包裹生成彈窗表單組件,代碼如下:

const submitForm = async (formValue: IUserFormValue) => {
  // TODO 表單提交邏輯
  console.log(formValue);
};

const UserFormModal = FormWrapper.withModal<IUserFormValue>({
  defaultValue: {
    name: "",
  },
  defaultProps: {
    onSubmit: submitForm,
  },
})(UserForm);

在實(shí)際業(yè)務(wù)場(chǎng)景中,彈窗表單和頁(yè)面表單都能復(fù)用一個(gè)表單組件,代碼如下:

const FormPage: React.FC = () => {
  const [form] = useForm<IUserFormValue>();

  const userFormRef = useRef<IFormWrapperRef<IUserFormValue>>(null);

  const handleSubmit = useCallback(() => {
    form.validate((error, formValue) => {
      if (error || !formValue) {
        return;
      }
      submitForm(formValue);
    });
  }, []);

  return (
    <div className="test-page">
      <h2>新建用戶</h2>

      {/* 頁(yè)面表單 */}
      <UserForm form={form} />
      <Button onClick={handleSubmit}>頁(yè)面新建</Button>

      {/* 彈窗表單 */}
      <UserFormModal ref={userFormRef} />
      <Button
        onClick={() => {
          userFormRef.current?.open({
            title: "新建用戶",
            mode: EFormMode.add,
            value: {
              name: "",
            },
          });
        }}
      >
        彈窗新建
      </Button>
    </div>
  );
};

3. 最后

表單容器的基于浮層容器進(jìn)行實(shí)現(xiàn),作者在實(shí)際業(yè)務(wù)開(kāi)發(fā)過(guò)程中也廣泛應(yīng)用到了這兩類容器,本篇也只是對(duì)簡(jiǎn)單表單場(chǎng)景進(jìn)行實(shí)現(xiàn),更為復(fù)雜的表單場(chǎng)景可以在評(píng)論區(qū)交流哈。

到此這篇關(guān)于React表單容器的通用解決方案的文章就介紹到這了,更多相關(guān)React表單容器內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • ReactQuery?渲染優(yōu)化示例詳解

    ReactQuery?渲染優(yōu)化示例詳解

    這篇文章主要為大家介紹了ReactQuery?渲染優(yōu)化示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-11-11
  • create-react-app中添加less支持的實(shí)現(xiàn)

    create-react-app中添加less支持的實(shí)現(xiàn)

    這篇文章主要介紹了react.js create-react-app中添加less支持的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-11-11
  • React中的Context應(yīng)用場(chǎng)景分析

    React中的Context應(yīng)用場(chǎng)景分析

    這篇文章主要介紹了React中的Context應(yīng)用場(chǎng)景分析,Context 提供了一種在組件之間共享數(shù)據(jù)的方式,而不必顯式地通過(guò)組件樹(shù)的逐層傳遞 props,通過(guò)實(shí)例代碼給大家介紹使用步驟,感興趣的朋友跟隨小編一起看看吧
    2021-06-06
  • React?Hooks鉤子中API的使用示例分析

    React?Hooks鉤子中API的使用示例分析

    在react類組件(class)寫法中,有setState和生命周期對(duì)狀態(tài)進(jìn)行管理,但是在函數(shù)組件中不存在這些,故引入hooks(版本:>=16.8),使開(kāi)發(fā)者在非class的情況下使用更多react特性
    2022-08-08
  • React中this丟失的四種解決方法

    React中this丟失的四種解決方法

    這篇文章主要給大家介紹了關(guān)于React中this丟失的四種解決方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者使用React具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-03-03
  • react-router實(shí)現(xiàn)跳轉(zhuǎn)傳值的方法示例

    react-router實(shí)現(xiàn)跳轉(zhuǎn)傳值的方法示例

    這篇文章主要給大家介紹了關(guān)于react-router實(shí)現(xiàn)跳轉(zhuǎn)傳值的相關(guān)資料,文中給出了詳細(xì)的示例代碼,對(duì)大家具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面跟著小編一起來(lái)學(xué)習(xí)學(xué)習(xí)吧。
    2017-05-05
  • react組件中過(guò)渡動(dòng)畫的問(wèn)題解決

    react組件中過(guò)渡動(dòng)畫的問(wèn)題解決

    這篇文章主要為大家介紹了react組件中過(guò)渡動(dòng)畫的問(wèn)題解決,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09
  • React中props使用介紹

    React中props使用介紹

    props是組件(包括函數(shù)組件和class組件)間的內(nèi)置屬性,用其可以傳遞數(shù)據(jù)給子節(jié)點(diǎn),props用來(lái)傳遞參數(shù)。組件實(shí)例化過(guò)程中,你可以向其中傳遞一個(gè)參數(shù),這個(gè)參數(shù)會(huì)在實(shí)例化過(guò)程中被引用
    2022-12-12
  • React實(shí)現(xiàn)監(jiān)聽(tīng)粘貼事件并獲取粘貼板中的截圖

    React實(shí)現(xiàn)監(jiān)聽(tīng)粘貼事件并獲取粘貼板中的截圖

    這篇文章主要介紹了React實(shí)現(xiàn)監(jiān)聽(tīng)粘貼事件并獲取粘貼板中的截圖方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-08-08
  • React State狀態(tài)與生命周期的實(shí)現(xiàn)方法

    React State狀態(tài)與生命周期的實(shí)現(xiàn)方法

    這篇文章主要介紹了React State狀態(tài)與生命周期的實(shí)現(xiàn)方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-03-03

最新評(píng)論

成武县| 海盐县| 门源| 邵武市| 宿州市| 柳河县| 孝义市| 锡林浩特市| 翁牛特旗| 平遥县| 措勤县| 遵义市| 枣庄市| 博湖县| 冷水江市| 乌拉特前旗| 顺义区| 察隅县| 淮北市| 迭部县| 冷水江市| 肇源县| 盐亭县| 富川| 元朗区| 平安县| 英山县| 通渭县| 林甸县| 沭阳县| 苍溪县| 奎屯市| 宁陕县| 冀州市| 托克托县| 惠安县| 东方市| 迭部县| 横山县| 小金县| 喜德县|