记一些题

94 阅读3分钟

实现一个函数,可以将数组转化为树状数据结构

// 入参格式参考:
const arr = [
  { id: 1, name: "i1" },
  { id: 2, name: "i2", parentId: 1 },
  { id: 4, name: "i4", parentId: 3 },
  { id: 3, name: "i3", parentId: 2 },
  { id: 8, name: "i8", parentId: 7 }
];
// 出参格式可自行设计, 举例:
{
  id: 1,
  name: 'i1',
  children: [
    {
      id: 2,
      name: 'i2',
      children: []
    }
  ]
}

function buildTree(arr) {
 let result = []
    let map = {}
    if (!Array.isArray(data)) {//验证data是不是数组类型
        return []
    }
    data.forEach(item => {//建立每个数组元素id和该对象的关系
        map[item.id] = item //这里可以理解为浅拷贝,共享引用
    })
    data.forEach(item => {
        let parent = map[item.parentId] //找到data中每一项item的爸爸
        if (parent) {//说明元素有爸爸,把元素放在爸爸的children下面
            (parent.children || (parent.children = [])).push(item)
        } else {//说明元素没有爸爸,是根节点,把节点push到最终结果中
            result.push(item) //item是对象的引用
        }
    })
    return result //数组里的对象和data是共享的
  
}

实现一个 arrange 函数/class,可以进行时间和工作调度

// [ > … ] 表示调用函数后的打印内容

// arrange('William').execute();
// > William is notified

// arrange('William').do('commit').execute();
// > William is notified
// > Start to commit

// arrange('William').wait(5).do('commit').execute();
// > William is notified
// 等待 5 秒
// > Start to commit

// arrange('William').waitFirst(5).do('push').execute();
// 等待 5 秒
// > William is notified
// > Start to push


代码

function arrange(taskId) {
  const tasks = [];
  tasks.push(() => {
    console.log(`${taskId} is notified`);
  });
  async function execute() {
    for (const t of tasks) {
      await t();
    }
  }
  function doSomething(something) {
    tasks.push(() => {
      console.log(`Start to ${something}`);
    });
    return this;
  }
  function wait(duration) {
    tasks.push(
      () =>
        new Promise((resolve) => {
          setTimeout(resolve, duration * 1000);
        })
    );
    return this;
  }
  function waitFirst(duration) {
    tasks.unshift(
      () =>
        new Promise((resolve) => {
          setTimeout(resolve, duration * 1000);
        })
    );
    return this;
  }
  return {
    execute,
    do: doSomething,
    wait,
    waitFirst,
  };
}



//或使用类组件, 如果使用类组件,调用形式可以改为: new arrange('William').execute();
class arrange {
  
}

自研数字键盘

要求:

  1. 请实现以下功能,并尽可能考虑异常场景的处理。附加题有余力请尽可能完成。
  2. 可以拆出多个组件来实现该功能

请使用React编程 实现下面的效果 (函数式或类组件均可)

功能描述:

  1. 自研数字键盘,能正常输入数字,点击退格键可以删除对应的数字。聚焦提现时唤起,失焦时隐藏。
  2. 输入数字的时候,左上分别有千、万、十万、百万、千万的提醒。
  3. 总免费额度为1000,超过部分提示收手续费0.1%。
  4. 总可用余额为3000,超出部分直接提醒文案标红,提现按钮不可点击
  5. 点击提现(能点击状态下)的时候出弹窗告诉是多少钱,提供一键清除输入功能。
  6. 附加题:本地展示最近3次提现记录。只要求功能实现,UI随意。
  7. 附加题:每次提现过后的免费额度和可用额度累计(即提现3次1000元,第2/3次收手续费,且之后不可再提现)。

import { useState, useRef } from 'react';

import { Input, Row, Col, InputRef, Modal, Button } from 'antd';

import { InfoCircleOutlined, CloseCircleOutlined } from '@ant-design/icons';



const returnFloat = (value: any) => {

  value = Math.round(parseFloat(value) * 100) / 100;

  let xsd = value.toString().split(".");

  if (xsd.length == 1) {

    value = value.toString() + ".00";

    return value;

  }

  if (xsd.length > 1) {

    if (xsd[1].length < 2) {

      value = value.toString() + "0";

    }

    return value;

  }

}

let numberMap = {

  4: '千',

  5: '万',

  6: '十万',

  7: '百万',

  8: '千万',

}

export default () => {

  const [value, setValue] = useState<any>('')

  const [isFocus, setIsFocus] = useState(false)

  const [cashHistory, setCashHistory] = useState([]) //显示的记录

  const [realCashHistory, setRealCashHistory] = useState([]) //实际的记录

  const [freeCash, setFreeCash] = useState(1000) //免费额度

  const [canGetMoney, setCanGetMoney] = useState(true) //是否可提现的标红



  const inputRef = useRef<InputRef>(null);



  const addMoney = (value: any) => {

    let realCashArr: any = [...realCashHistory]

    let total: number = 0

    realCashArr.map((item: any) => total += Number(item))

    console.log('total---', total)

    if (total + Number(value) > 3000) {

      return setCanGetMoney(false)

    } else {

      setCanGetMoney(true)

    }



  }

  return (

    <div onClick={() => setIsFocus(false)}>

      <div style={{ background: '#ffffff', padding: '10px' }} >

        <div>提现金额</div>

        <div style={{ marginLeft: 20, height: 30 }}>{value.split('.')[0].length > 3 ? `|${numberMap[value.split('.')[0].length]}` : ''}</div>

        <div style={{ display: 'flex', justifyContent: 'space-between' }}>

          <div style={{ display: 'flex' }}>

            <span>

              ¥

            </span>

            <div onClick={(e) => {

              e.stopPropagation()

              setIsFocus(true)

            }}>

              <Input style={{ width: 100, }}

                ref={inputRef}

                maxLength={8} value={value} />

              {

                isFocus ?

                  <div style={{ display: 'flex', position: 'fixed', bottom: 10, right: 0, width: '100% ' }}>

                    <div style={{ flex: 1, background: '#ffffff' }} >

                      <Row>

                        {['1', '2', '3', '4', '5', '6', '7', '8', '9'].map((item: string) =>

                          <Col span={8} style={{ textAlign: 'center', height: 30, borderBottom: '1px solid rgb(246 242 242)', borderRight: '1px solid rgb(246 242 242)' }}

                            onClick={(e: any) => {

                              //输入的时候

                              if (value.length < 8) {

                                if (value.includes('.')) {

                                  if (value.split('.')[1].length < 2) {

                                    setValue(value + e.target.textContent)

                                    addMoney(value + e.target.textContent)



                                  }

                                } else {

                                  setValue(value + e.target.textContent)

                                  addMoney(value + e.target.textContent)



                                }



                              }

                              inputRef.current!.focus({

                                cursor: 'end',

                              });



                            }}

                          >

                            {item}

                          </Col>

                        )}

                        <Col span={16} style={{ textAlign: 'center', height: 30, borderBottom: '1px solid rgb(246 242 242)', borderRight: '1px solid rgb(246 242 242)' }} onClick={(e: any) => {

                          if (value.length < 8) {

                            setValue(value + e.target.textContent)

                            addMoney(value + e.target.textContent)



                          }

                          inputRef.current!.focus({

                            cursor: 'end',

                          });



                        }}>

                          0

                        </Col>

                        <Col span={8} style={{ textAlign: 'center', height: 30, borderBottom: '1px solid rgb(246 242 242)', borderRight: '1px solid rgb(246 242 242)' }} onClick={(e: any) => {

                          if (value.length < 8) {

                            if (value) {

                              if (!value.includes('.')) {

                                setValue(value + e.target.textContent)

                                addMoney(value + e.target.textContent)

                              }

                            } else {

                              setValue('0' + e.target.textContent)

                              addMoney('0' + e.target.textContent + e.target.textContent)



                            }

                          }

                          inputRef.current!.focus({

                            cursor: 'end',

                          });



                        }}>

                          .

                        </Col>

                      </Row>

                    </div>

                    <div style={{ width: 60 }}>

                      <div style={{ textAlign: 'center', background: '#ffffff', height: 30 }} >

                        <CloseCircleOutlined onClick={() => {



                          setValue(value.slice(0, value.length - 1))

                          addMoney(value.slice(0, value.length - 1))



                          inputRef.current!.focus({

                            cursor: 'end',

                          });

                        }} />

                      </div>

                      <div style={{ background: value && Number(value) < 3000 && canGetMoney ? 'blue' : 'grey', display: 'flex', alignItems: 'center', justifyContent: 'center', height: 90, }}

                        onClick={() => {

                          if (value && Number(value) < 3000 && canGetMoney) {

                            Modal.confirm({

                              title: `提现金额一共${value}元`,

                              content: (

                                <>

                                  <Button onClick={() => {

                                    setValue('')

                                    Modal.destroyAll()

                                  }}>一键清除</Button>

                                </>

                              ),

                              onOk: async () => {

                                if (cashHistory.length < 3) {

                                  let arr: any = [...cashHistory]

                                  arr.push(value)

                                  setCashHistory(arr)

                                } else {

                                  let arr: any = [...cashHistory]

                                  arr.shift()

                                  arr.push(value)

                                  setCashHistory(arr)

                                }

                                let realCashArr: any = [...realCashHistory]

                                realCashArr.push(value)

                                setRealCashHistory(realCashArr)

                                setCanGetMoney(true)

                                freeCash - value > 0 ? setFreeCash(freeCash - value) : setFreeCash(0)

                                setValue('')

                              }

                            })

                          }

                        }}

                      >提现</div>

                    </div>

                  </div>

                  :

                  null

              }

            </div>

          </div>

          {

            true ? <CloseCircleOutlined onClick={(e) => {

              e.stopPropagation()

              setValue('')

            }} />

              :

              <div>

                <span>全部提现</span>

                <span>¥30000</span>

              </div>

          }



        </div>

        <div>

          {

            freeCash > 0 ?

              <span>         免费额度还剩{freeCash}元,超出部分收取0.1%服务费         <InfoCircleOutlined /></span>

              :

              canGetMoney ?

                <span>         预计收取服务费¥{returnFloat(Number(value) * 0.001)}       <InfoCircleOutlined /></span>

                :

                <span style={{ color: 'red' }}>        超出可用余额¥3000      </span>



          }



        </div>

        <div>

          {cashHistory.length ? <div>

            {cashHistory.map((item: any, index: number) => {

              return <div>

                第{index + 1}次提现:{item}元

              </div>

            })}

          </div> : ''}

        </div>

      </div>



    </div >

  );

};