|
@@ -1,338 +0,0 @@
|
|
|
-import React, { useRef, useState } from 'react';
|
|
|
-import {
|
|
|
- ActionType,
|
|
|
- PageContainer,
|
|
|
- ProForm,
|
|
|
- ProFormDateRangePicker,
|
|
|
- ProFormText,
|
|
|
- ProTable,
|
|
|
-} from '@ant-design/pro-components';
|
|
|
-import { Button, Calendar, Card, Image, Modal, Popover, Tabs, Tag } from 'antd';
|
|
|
-import { AddOutline } from 'antd-mobile-icons';
|
|
|
-import { EditBundle, useEdit } from '@/core/hooks/useEdit';
|
|
|
-import UIImage from '@/core/ui/UIImage';
|
|
|
-import { v4 } from 'uuid';
|
|
|
-import { invoke } from '@/core/network';
|
|
|
-import dayjs from 'dayjs';
|
|
|
-
|
|
|
-export interface LaunchImage {
|
|
|
- id: number;
|
|
|
- title: string;
|
|
|
- uri: string;
|
|
|
- effectiveTime: string;
|
|
|
- takeDownTime: string;
|
|
|
-}
|
|
|
-
|
|
|
-export interface LaunchImageList {
|
|
|
- records: LaunchImage[];
|
|
|
- total: number;
|
|
|
- size: number;
|
|
|
- current: number;
|
|
|
-}
|
|
|
-
|
|
|
-class Service {
|
|
|
- public static async list(current: number, size: number) {
|
|
|
- return invoke<LaunchImageList>('/apis/admin/launch_img/page', {
|
|
|
- method: 'POST',
|
|
|
- data: {
|
|
|
- current,
|
|
|
- size,
|
|
|
- },
|
|
|
- });
|
|
|
- }
|
|
|
-
|
|
|
- public static async get(id: number) {
|
|
|
- return invoke<LaunchImage>('/apis/admin/launch_img/details', {
|
|
|
- method: 'GET',
|
|
|
- params: {
|
|
|
- id,
|
|
|
- },
|
|
|
- });
|
|
|
- }
|
|
|
-
|
|
|
- public static async remove(id: number) {
|
|
|
- return invoke<void>(`/apis/admin/launch_img/remove?id=${id}`, {
|
|
|
- method: 'DELETE',
|
|
|
- });
|
|
|
- }
|
|
|
-
|
|
|
- public static async save(image: Partial<LaunchImage>) {
|
|
|
- return invoke<LaunchImage>('/apis/admin/launch_img/save', {
|
|
|
- method: 'POST',
|
|
|
- data: image,
|
|
|
- });
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-type Screen = {
|
|
|
- id: number;
|
|
|
- title: string;
|
|
|
- image: string;
|
|
|
- date: string[];
|
|
|
-};
|
|
|
-
|
|
|
-const Edit: React.FC<{ bundle: EditBundle; onSuccess?: () => void }> = (props) => {
|
|
|
- const { bundle } = props;
|
|
|
- const [form] = ProForm.useForm();
|
|
|
- const [loading, setLoading] = useState<boolean>(false);
|
|
|
-
|
|
|
- return (
|
|
|
- <Modal
|
|
|
- confirmLoading={loading}
|
|
|
- open={bundle.open}
|
|
|
- title={bundle.id ? '编辑开机屏' : '添加开机屏'}
|
|
|
- onCancel={() => {
|
|
|
- bundle.close();
|
|
|
- }}
|
|
|
- onClose={() => {
|
|
|
- bundle.close();
|
|
|
- }}
|
|
|
- onOk={async () => {
|
|
|
- await form.validateFields();
|
|
|
-
|
|
|
- try {
|
|
|
- setLoading(true);
|
|
|
- const values = form.getFieldsValue();
|
|
|
-
|
|
|
- const res = await Service.save({
|
|
|
- id: bundle.id,
|
|
|
- title: values.title,
|
|
|
- uri: values.image.name,
|
|
|
- effectiveTime: values.date[0].format('YYYY-MM-DD HH:mm:ss'),
|
|
|
- takeDownTime: values.date[1].format('YYYY-MM-DD HH:mm:ss'),
|
|
|
- });
|
|
|
-
|
|
|
- if (!res.success) {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- props.onSuccess?.();
|
|
|
- bundle.close();
|
|
|
- } finally {
|
|
|
- setLoading(false);
|
|
|
- }
|
|
|
- }}
|
|
|
- >
|
|
|
- <ProForm
|
|
|
- className={'mt-5'}
|
|
|
- form={form}
|
|
|
- layout={'horizontal'}
|
|
|
- labelCol={{ span: 4 }}
|
|
|
- submitter={false}
|
|
|
- request={async () => {
|
|
|
- if (bundle.id) {
|
|
|
- const data = await Service.get(bundle.id);
|
|
|
-
|
|
|
- return {
|
|
|
- title: data.data.title,
|
|
|
- image: data.data.uri,
|
|
|
- date: [data.data.effectiveTime, data.data.takeDownTime],
|
|
|
- };
|
|
|
- }
|
|
|
-
|
|
|
- return Promise.resolve({
|
|
|
- image: {
|
|
|
- name: `screen/${v4()}`,
|
|
|
- },
|
|
|
- });
|
|
|
- }}
|
|
|
- >
|
|
|
- <ProFormText name={'title'} label={'标题'} required={true} />
|
|
|
- <ProForm.Item name={'image'} label={'图片'} required={true}>
|
|
|
- <UIImage className={'h-[180px]'}></UIImage>
|
|
|
- </ProForm.Item>
|
|
|
- <ProFormDateRangePicker
|
|
|
- name={'date'}
|
|
|
- label={'生效时间'}
|
|
|
- rules={[
|
|
|
- {
|
|
|
- required: true,
|
|
|
- message: '请选择生效时间区间',
|
|
|
- },
|
|
|
- ]}
|
|
|
- ></ProFormDateRangePicker>
|
|
|
- </ProForm>
|
|
|
- </Modal>
|
|
|
- );
|
|
|
-};
|
|
|
-
|
|
|
-const Screens: React.FC<{}> = (props) => {
|
|
|
- const edit = useEdit();
|
|
|
- const ref = useRef<ActionType>();
|
|
|
- const [records, setRecords] = useState<LaunchImage[]>([]);
|
|
|
-
|
|
|
- const modeTable = () => {
|
|
|
- return (
|
|
|
- <ProTable<Screen>
|
|
|
- rowKey={'id'}
|
|
|
- request={async (params) => {
|
|
|
- const res = await Service.list(params.current || 1, params.pageSize || 10);
|
|
|
-
|
|
|
- setRecords(res.data.records);
|
|
|
-
|
|
|
- console.log(res.data.records, 'records');
|
|
|
-
|
|
|
- return {
|
|
|
- success: res.success,
|
|
|
- total: res.data.total,
|
|
|
- data: res.data.records.map((record) => {
|
|
|
- return {
|
|
|
- id: record.id,
|
|
|
- title: record.title,
|
|
|
- image: record.uri,
|
|
|
- date: [record.effectiveTime, record.takeDownTime],
|
|
|
- };
|
|
|
- }),
|
|
|
- };
|
|
|
- }}
|
|
|
- columns={[
|
|
|
- {
|
|
|
- title: 'ID',
|
|
|
- dataIndex: 'id',
|
|
|
- },
|
|
|
- {
|
|
|
- title: '标题',
|
|
|
- dataIndex: 'title',
|
|
|
- },
|
|
|
- {
|
|
|
- title: '图片',
|
|
|
- dataIndex: 'image',
|
|
|
- render: (node, record) => {
|
|
|
- return <img src={record.image} alt={record.title} className={'w-[64px]'} />;
|
|
|
- },
|
|
|
- },
|
|
|
- {
|
|
|
- title: '生效时间',
|
|
|
- dataIndex: 'date',
|
|
|
- valueType: 'dateRange',
|
|
|
- },
|
|
|
- {
|
|
|
- title: '操作',
|
|
|
- valueType: 'option',
|
|
|
- render: (_, record) => [
|
|
|
- <a key={'edit'} onClick={() => edit.update(record.id)}>
|
|
|
- 编辑
|
|
|
- </a>,
|
|
|
- <a
|
|
|
- key={'delete'}
|
|
|
- onClick={async () => {
|
|
|
- await Service.remove(record.id);
|
|
|
- ref.current?.reload();
|
|
|
- }}
|
|
|
- >
|
|
|
- 删除
|
|
|
- </a>,
|
|
|
- ],
|
|
|
- },
|
|
|
- ]}
|
|
|
- actionRef={ref}
|
|
|
- search={false}
|
|
|
- toolbar={{
|
|
|
- actions: [
|
|
|
- <Button key="add" type="primary" icon={<AddOutline />} onClick={() => edit.create()}>
|
|
|
- 添加
|
|
|
- </Button>,
|
|
|
- ],
|
|
|
- settings: [],
|
|
|
- }}
|
|
|
- ></ProTable>
|
|
|
- );
|
|
|
- };
|
|
|
-
|
|
|
- const stringToColor = (str: string): string => {
|
|
|
- // 计算字符串的哈希值
|
|
|
- let hash = 0;
|
|
|
- for (let i = 0; i < str.length; i++) {
|
|
|
- const char = str.charCodeAt(i);
|
|
|
- hash = (hash << 5) - hash + char;
|
|
|
- hash |= 0; // 转换为32位整数
|
|
|
- }
|
|
|
-
|
|
|
- // 使用哈希值的低位来生成 RGB 颜色
|
|
|
- let r = (hash & 0xff0000) >> 16;
|
|
|
- let g = (hash & 0x00ff00) >> 8;
|
|
|
- let b = hash & 0x0000ff;
|
|
|
-
|
|
|
- // 混合颜色使其变浅
|
|
|
- const mix = (color: number, base: number): number => Math.round((color + base) / 2.4);
|
|
|
- r = mix(r, 255);
|
|
|
- g = mix(g, 255);
|
|
|
- b = mix(b, 255);
|
|
|
-
|
|
|
- // 将 RGB 值转换为十六进制字符串,并确保两位数
|
|
|
- const toHex = (n: number): string => n.toString(16).padStart(2, '0');
|
|
|
-
|
|
|
- // 返回颜色的十六进制表示
|
|
|
- return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
|
|
|
- };
|
|
|
-
|
|
|
- const modeCalendar = () => {
|
|
|
- return (
|
|
|
- <Calendar
|
|
|
- cellRender={(date) => {
|
|
|
- const items = records.filter((i) => {
|
|
|
- const effect = dayjs(i.effectiveTime);
|
|
|
- const take = dayjs(i.takeDownTime);
|
|
|
-
|
|
|
- //date between [effect,take]
|
|
|
- return date.isAfter(effect) && date.isBefore(take);
|
|
|
- });
|
|
|
-
|
|
|
- return (
|
|
|
- <div className={'flex flex-col gap-2'}>
|
|
|
- {items.map((i, index) => {
|
|
|
- return (
|
|
|
- <Popover
|
|
|
- key={`${index}`}
|
|
|
- title={i.title}
|
|
|
- content={
|
|
|
- <div>
|
|
|
- <Image src={i.uri} width={120}></Image>
|
|
|
- </div>
|
|
|
- }
|
|
|
- >
|
|
|
- <Tag
|
|
|
- key={`${index}`}
|
|
|
- style={{ borderRadius: 5 }}
|
|
|
- color={stringToColor(i.title)}
|
|
|
- onClick={() => {
|
|
|
- console.log('click');
|
|
|
- }}
|
|
|
- >
|
|
|
- {i.title}
|
|
|
- </Tag>
|
|
|
- </Popover>
|
|
|
- );
|
|
|
- })}
|
|
|
- </div>
|
|
|
- );
|
|
|
- }}
|
|
|
- ></Calendar>
|
|
|
- );
|
|
|
- };
|
|
|
-
|
|
|
- return (
|
|
|
- <PageContainer>
|
|
|
- {edit.open && <Edit bundle={edit} onSuccess={() => ref.current?.reload()}></Edit>}
|
|
|
- <Card>
|
|
|
- <Tabs
|
|
|
- defaultActiveKey={'1'}
|
|
|
- items={[
|
|
|
- {
|
|
|
- label: '表单模式',
|
|
|
- key: '1',
|
|
|
- children: modeTable(),
|
|
|
- },
|
|
|
- {
|
|
|
- label: '日历模式',
|
|
|
- key: '2',
|
|
|
- children: modeCalendar(),
|
|
|
- },
|
|
|
- ]}
|
|
|
- ></Tabs>
|
|
|
- </Card>
|
|
|
- </PageContainer>
|
|
|
- );
|
|
|
-};
|
|
|
-
|
|
|
-export default Screens;
|