Эх сурвалжийг харах

Merge branch 'master' of http://787255.xyz:4003/ydm/zl365

杨东明 7 сар өмнө
parent
commit
f57cd7def8

+ 1 - 0
package.json

@@ -4,6 +4,7 @@
   "private": true,
   "dependencies": {
     "@fluentui/react-components": "^9.55.1",
+    "@fluentui/react-datepicker-compat": "^0.4.53",
     "@fluentui/react-icons": "^2.0.264",
     "@testing-library/jest-dom": "^5.17.0",
     "@testing-library/react": "^13.4.0",

BIN
public/img/zl_bg.jpg


+ 3 - 0
src/component/card/index.css

@@ -1,3 +1,6 @@
 .card-height > div {
   flex-direction: row !important;
+}
+img.card-bg {
+  max-height: 200px;
 }

+ 10 - 11
src/component/card/index.tsx

@@ -50,15 +50,15 @@ const useStyles = makeStyles({
 });
 
 
-const CardExample = (props: CardProps) => {
+const CardExample = (props: any) => {
   const styles = useStyles();
 
   return (
     <Card className={styles.card} {...props}>
       <CardPreview>
-        <img
-          src={resolveAsset("sales_template.png")}
-          alt="Sales Presentation Preview"
+        <img className="card-bg"
+          src={("../../img/zl_bg.jpg")}
+          alt="中联背景图"
         />
       </CardPreview>
 
@@ -73,10 +73,10 @@ const CardExample = (props: CardProps) => {
         }
         header={
           <Body1>
-            <b>App Name</b>
+            <b>{props.name}</b>
           </Body1>
         }
-        description={<Caption1>Developer</Caption1>}
+        description={<Caption1>新技术工作室</Caption1>}
         action={
           <Button
             appearance="transparent"
@@ -87,8 +87,7 @@ const CardExample = (props: CardProps) => {
       />
 
       <p className={styles.text}>
-        Donut chocolate bar oat cake. Dragée tiramisu lollipop bear claw.
-        Marshmallow pastry jujubes toffee sugar plum.
+        平时积极乐观、热爱工作、喜欢看书、回家后喜欢运动
       </p>
     </Card>
   );
@@ -100,15 +99,15 @@ export const FocusMode = () => {
   return (
     <div className={styles.main}>
       <section>
-        <CardExample />
+        <CardExample name="吴瑞强" />
       </section>
 
       <section>
-        <CardExample focusMode="no-tab" />
+        <CardExample focusMode="no-tab" name="杨东明"/>
       </section>
 
       <section>
-        <CardExample focusMode="tab-exit" />
+        <CardExample focusMode="tab-exit" name="唐渝林" />
       </section>
     </div>
   );

+ 15 - 11
src/component/content/index.css

@@ -69,17 +69,18 @@ button.btngroup-btn {
         color: var(--colorBrandBackground);
     }
 
-a.content-side-li-nav {
-    color: #323130;
-    padding-left: 30px;
-    height: 44px;
-    line-height: 44px;
-    position: relative;
-    display: inline-block;
-    font-style: var(--fontStyleRegular);
-    font-size: var(--fontSizeBase300);
-    font-weight: var(--fontWeightCustomFont500, var(--fontWeightRegular));
-}
+    a.content-side-li-nav {
+        color: #323130;
+        padding-left: 30px;
+        height: 44px;
+        line-height: 44px;
+        position: relative;
+        display: inline-block;
+        font-style: var(--fontStyleRegular);
+        font-size: var(--fontSizeBase300);
+        font-weight: var(--fontWeightCustomFont500, var(--fontWeightRegular));
+        text-decoration: none;
+    }
 
 .zl-365-content-side-li:hover {
     background: #faf9f8;
@@ -159,4 +160,7 @@ a.content-side-li-nav {
     flex: 0 0 calc(100% - 227px);
     max-width: calc(100% - 227px); 
     padding: 8px;
+}
+.content-header-img-name {
+    align-self: center;
 }

+ 55 - 0
src/component/form/index.css

@@ -0,0 +1,55 @@
+.layout-col-12.form-height {
+    padding: 16px;
+}
+
+.layout-col-12.card-height {
+    padding: 16px;
+}
+
+.layout-main {
+    height: calc(100vh - 145px);
+    overflow: auto;
+}
+
+.layout-col-12.form-height > div > div {
+    flex: 1 1 33.333333%;
+    max-width: 33.3333333%;
+    gap: 0;
+    padding: 8px;
+}
+
+.layout-col-12.form-height > div {
+    display: flex;
+    width: 100%;
+    max-width: 100%;
+    flex-wrap: wrap;
+    flex-direction: row;
+    gap: 0;
+}
+
+div#field-ra__control {
+    flex-direction: row;
+}
+
+.form-btn {
+    display: flex;
+    flex-direction: row;
+}
+.checkbox-form > div {
+    display: flex;
+}
+
+.form-btngroup {
+    display: flex;
+    flex-direction: row !important;
+    align-items: flex-end;
+}
+
+.form-btngroup > button {
+    flex-grow: 1;
+    margin: 16px;
+    min-height: 35px;
+}
+.radio-form > div > div {
+    flex-direction: row;
+}

+ 135 - 0
src/component/form/index.tsx

@@ -0,0 +1,135 @@
+import * as React from "react";
+import {
+  makeStyles,
+  useId,
+  Button,
+  Input,
+  Label,
+  Text,
+  Select,
+  Checkbox,
+  Field,
+  Textarea,
+  Radio,
+  RadioGroup
+} from "@fluentui/react-components";
+import {
+  PersonRegular,
+  MicRegular,
+  bundleIcon,
+  CalendarMonthFilled,
+  CalendarMonthRegular,
+} from "@fluentui/react-icons";
+import type { ButtonProps } from "@fluentui/react-components";
+import { DatePicker } from "@fluentui/react-datepicker-compat";
+import "./index.css"
+const useStyles = makeStyles({
+  root: {
+    display: "flex",
+    flexDirection: "column",
+    gap: "20px",
+    // Prevent the example from taking the full width of the page (optional)
+    maxWidth: "400px",
+    // Stack the label above the field (with 2px gap per the design system)
+    "> div": { display: "flex", flexDirection: "column", gap: "2px" },
+  },
+});
+
+const MicButton: React.FC<ButtonProps> = (props) => {
+  return (
+    <Button
+      {...props}
+      appearance="transparent"
+      icon={<MicRegular />}
+      size="small"
+    />
+  );
+};
+
+export const ContentBeforeAfter = () => {
+  const styles = useStyles();
+
+  const beforeId = useId("content-before");
+  const afterId = useId("content-after");
+  const beforeAndAfterId = useId("content-before-and-after");
+  const beforeLabelId = useId("before-label");
+  const afterLabelId = useId("after-label");
+
+  return (
+    <div className={styles.root}>
+      <div>
+        <Label htmlFor={beforeId}>姓名</Label>
+        <Input contentBefore={<PersonRegular />} id={beforeId} />
+      </div>
+
+      <div>
+        <Label htmlFor={afterId}>地址</Label>
+        <Input
+          contentAfter={<MicButton aria-label="Enter by voice" />}
+          id={afterId}
+        />
+      </div>
+
+      <div>
+        <Label htmlFor={beforeAndAfterId}>费用</Label>
+        <Input
+          contentBefore={
+            <Text size={400} id={beforeLabelId}>
+              $
+            </Text>
+          }
+          contentAfter={
+            <Text size={400} id={afterLabelId}>
+              .00
+            </Text>
+          }
+          aria-labelledby={`${beforeAndAfterId} ${beforeLabelId} ${afterLabelId}`}
+          id={beforeAndAfterId}
+        />
+      </div>
+      <div className="radio-form">
+        <Field label="性别">
+          <RadioGroup>
+            <Radio value="apple" label="男" />
+            <Radio value="pear" label="女" />
+            <Radio value="banana" label="未知" />
+          </RadioGroup>
+        </Field>
+      </div>
+      <div className="checkbox-form">
+        <Label htmlFor={beforeAndAfterId}>爱好</Label>
+        <Field>
+            <Checkbox label="写代码" />
+            <Checkbox label="看书" />
+            <Checkbox label="健身" />
+        </Field>
+      </div>
+      <div>
+        <label>颜色</label>
+        <Select>
+          <option>Red</option>
+          <option>Green</option>
+          <option>Blue</option>
+        </Select>
+      </div>
+      <div>
+        <Field label="Select a date">
+          <DatePicker placeholder="Select a date..." />
+        </Field>
+      </div>
+      <div>
+        <Field label="备注">
+          <Textarea />
+        </Field>
+      </div>
+      <div className="form-btngroup">
+        <Button appearance="primary" icon={<CalendarMonthRegular />}>
+          确定
+        </Button>
+        <Button appearance="outline" icon={<CalendarMonthFilled />}>
+          取消
+        </Button>
+      </div>
+    </div>
+  );
+};

+ 28 - 8
src/component/hedaer/index.css

@@ -4,7 +4,7 @@
 }
 
 .zl-365-header {
-    background-color: #004d88;
+    background-color: var(--colorBrandBackground);
     display: flex;
     flex-wrap: nowrap;
     align-items: center;
@@ -12,6 +12,10 @@
     max-width: 100%;
 }
 
+.zl-365-header-search > span {
+    width: 400px;
+}
+
 .zl-365-logo-search {
     display: flex;
     flex-wrap: nowrap;
@@ -21,7 +25,7 @@
     position: absolute;
     left: 9px;
     top: 9px;
-    color: #0078d4;
+    color: var(--colorBrandBackground);
 }
 
 .header-logo-input {
@@ -73,16 +77,16 @@ span.header-search-svg {
     position: relative;
     left: 30px;
     top: 3px;
-    color: #0078d4;
+    color: var(--colorBrandBackground);
 }
 
 .zl-365-header-function:hover {
-    background-color: #004d88;
+    background-color: var(--colorBrandBackground);
     cursor: pointer;
 }
 
 .zl-365-header-tools>div:hover {
-    background-color: #065693;
+    background-color: var(--colorBrandBackground);
     cursor: pointer;
 }
 
@@ -204,7 +208,7 @@ input:focus {
 }
 
 input.header-logo-input:hover:after {
-    border-bottom: 2px solid #0f6cbd;
+    border-bottom: 2px solid var(--colorBrandBackground);
     position: absolute;
     content: '';
     width: 100%;
@@ -220,9 +224,25 @@ span.header-loge-input:hover:after {
     right: 0;
     width: 100%;
     height: 2px;
-    border-bottom: 2px solid #0f6cbd;
+    border-bottom: 2px solid var(--colorBrandBackground);
 }
 
 span.header-loge-input {
     position: relative;
-}
+}
+
+span.header-loge-input > span {
+    width: 100%;
+}
+
+span.header-loge-input {
+    width: 100%;
+    padding: 0 8px;
+}
+.zl-365-logo-search > span {
+    width: 100%;
+}
+
+.zl-365-logo-search {
+    padding: 0 16px;
+}

+ 7 - 28
src/component/hedaer/index.jsx

@@ -5,9 +5,13 @@ import {
     mergeClasses,
     Button,
     Popover,
+    Input,
     PopoverSurface,
     PopoverTrigger,
 } from "@fluentui/react-components";
+import {
+    SearchRegular,
+} from "@fluentui/react-icons";
 import m365 from "../../img/m365.svg";
 import outlook from "../../img/outlook.svg";
 import oneDrice from "../../img/oneDrice.svg";
@@ -133,10 +137,7 @@ const PositionedComponent = (props) => {
                     class="zl-365-header-tools2"
                 >
                     <div class="zl-365-logo-search">
-                        <span class="header-loge-input">
-                            <span class="header-logo-svg"><svg t="1730778975282" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="22289" width="16" height="16"><path d="M314.445 652.986l-190.73 190.73c-15.62 15.62-15.62 40.947 0 56.568 15.622 15.621 40.948 15.621 56.57 0l190.729-190.73C433.062 759.268 511.809 789 597.5 789 797.703 789 960 626.703 960 426.5S797.703 64 597.5 64 235 226.297 235 426.5c0 85.691 29.733 164.438 79.445 226.486zM597.5 709C441.48 709 315 582.52 315 426.5 315 270.48 441.48 144 597.5 144 753.52 144 880 270.48 880 426.5 880 582.52 753.52 709 597.5 709z" fill="currentColor" p-id="22290"></path></svg></span>
-                            <input type="text" class="header-logo-input" placeholder="查找Microsoft 365应用" />
-                        </span>
+                        <Input placeholder="查找Microsoft 365应用" contentBefore={<SearchRegular />} />
                     </div>
                 </div>
                 <div style={{ width: "480px", height: "409px" }}>
@@ -576,7 +577,7 @@ const IconHtml = () => {
 
 
 const ChangeTheme = (name) => {
-    
+
 }
 
 
@@ -590,29 +591,7 @@ const Header = () => {
             </div>
             <div class="zl-365-header-name">ZlSoftSharePoint</div>
             <div class="zl-365-header-search">
-                <span class="header-search-svg">
-                    <svg
-                        t="1730778975282"
-                        class="icon"
-                        viewBox="0 0 1024 1024"
-                        version="1.1"
-                        xmlns="http://www.w3.org/2000/svg"
-                        p-id="22289"
-                        width="16"
-                        height="16"
-                    >
-                        <path
-                            d="M314.445 652.986l-190.73 190.73c-15.62 15.62-15.62 40.947 0 56.568 15.622 15.621 40.948 15.621 56.57 0l190.729-190.73C433.062 759.268 511.809 789 597.5 789 797.703 789 960 626.703 960 426.5S797.703 64 597.5 64 235 226.297 235 426.5c0 85.691 29.733 164.438 79.445 226.486zM597.5 709C441.48 709 315 582.52 315 426.5 315 270.48 441.48 144 597.5 144 753.52 144 880 270.48 880 426.5 880 582.52 753.52 709 597.5 709z"
-                            fill="currentColor"
-                            p-id="22290"
-                        ></path>
-                    </svg>
-                </span>
-                <input
-                    type="text"
-                    class="header-search-input"
-                    placeholder="在SharePoint中搜索"
-                />
+                <Input placeholder="在此网站中搜索" contentBefore={<SearchRegular />} />
             </div>
             <div class="zl-365-header-tools">
                 <Menu>

BIN
src/img/zlsoft.png


+ 21 - 0
src/pages/home/index.css

@@ -0,0 +1,21 @@
+.layout-col-4 {
+    flex: 0 0 33.33333%;
+    max-width: 33.33333%;
+    padding: 16px;
+}
+
+.layout-col-8 {
+    flex: 0 0 66.66666%;
+    max-width: 66.66666%;
+    padding: 16px;
+}
+
+.layout-row {
+    display: flex;
+    flex-wrap: wrap;
+}
+label.layout-title {
+    font-size: 18px;
+    font-weight: 600;
+    padding: 8px;
+}

+ 33 - 18
src/pages/home/index.tsx

@@ -1,25 +1,40 @@
 import React from "react";
 import { useTranslation } from "react-i18next";
-import {FocusMode as Card} from '../../component/card';
+import { FocusMode as Card } from "../../component/card";
+import { ContentBeforeAfter as Form } from "../../component/form";
+import List from "../listnew";
+import Tree from "../../component/tree";
 
+import "./index.css";
+import { Button, FluentProvider } from "@fluentui/react-components";
 function MyNavlink() {
-    const { t } = useTranslation();
-    return (
-        <div className="layout-main">
-            <div className="layout-row">
-                <div className="layout-col-12 card-height">
-                    <Card></Card>
-                </div>
-            </div>
-            <div className="layout-row">
-                <div className="layout-col-4 tree-height"></div>
-                <div className="layout-col-8 list-height"></div>
-            </div>
-            <div className="layout-row">
-                <div className="layout-col-12 form-height"></div>
-            </div>
+  const { t } = useTranslation();
+  return (
+    <div className="layout-main">
+      <div className="layout-row">
+        <label className="layout-col-12 layout-title">卡片组件</label>
+        <div className="layout-col-12 card-height">
+          <Card></Card>
         </div>
-    );
+      </div>
+      <div className="layout-row">
+        <label className="layout-col-4 layout-title">树形组件</label>
+        <label className="layout-col-8 layout-title">列表组件</label>
+        <div className="layout-col-4 tree-height">
+          <Tree></Tree>
+        </div>
+        <div className="layout-col-8 list-height">
+          <List></List>
+        </div>
+      </div>
+      <div className="layout-row">
+      <label className="layout-col-12 layout-title">表单组件</label>
+        <div className="layout-col-12 form-height">
+          <Form />
+        </div>
+      </div>
+    </div>
+  );
 }
 
-export default MyNavlink;
+export default MyNavlink;

+ 87 - 54
src/pages/listnew/index.jsx

@@ -11,7 +11,8 @@ import {
   SelectAllOn16Regular,
   CommentAdd16Regular,
   MoreHorizontal16Filled,
-  NumberCircle116Regular
+  NumberCircle116Regular,
+  Add16Filled
 } from "@fluentui/react-icons";
 import {
   DataGridBody,
@@ -30,11 +31,14 @@ import {
   MenuPopover,
   Tooltip,
   MenuDivider,
+  Input,
+  Select,
 } from "@fluentui/react-components";
+import { DatePicker } from "@fluentui/react-datepicker-compat";
 
 
-const List = () => {
-  const defaultSelectedItems = React.useMemo(() => new Set([1]), []);
+const List = (editType) => {
+  // const defaultSelectedItems = React.useMemo(() => new Set([1]), []);
 
   //数据类型常量
   const DATA_TYPE = {
@@ -196,7 +200,8 @@ const List = () => {
         onMouseEnter={handleMouseEnter}
         onMouseLeave={handleMouseLeave}
       >
-        {props.cellData}
+
+        {editType.edit == "true" ? <Input type="text" style={{ width: "calc(100% - 70px)" }} defaultValue={props.cellData} /> : props.cellData}
         {showButton && (
           <div>
             <Tooltip content="更多操作" positioning="below">
@@ -217,74 +222,92 @@ const List = () => {
     );
   };
 
+  const tableData = [
+    {
+      序号: { label: 1 },
+      姓名: { label: "陈丹" },
+      性别: { label: "女" },
+      年龄: { label: "18岁" },
+      最后在线时间: { label: "2024-11-03" },
+    },
+    {
+      序号: { label: 2 },
+      姓名: { label: "蔡青松" },
+      性别: { label: "男", },
+      年龄: { label: "30岁" },
+      最后在线时间: { label: "2024-11-04" },
+    },
+    {
+      序号: { label: 3 },
+      姓名: { label: "杨东明" },
+      性别: { label: "男" },
+      年龄: { label: "25岁" },
+      最后在线时间: { label: "2024-11-05" },
+    },
+    {
+      序号: { label: 4 },
+      姓名: { label: "吴瑞强" },
+      性别: { label: "男" },
+      年龄: { label: "25岁" },
+      最后在线时间: { label: "2024-11-06" },
+    },
+  ]
+
+  const [newTableData, setTabeData] = useState(tableData);
+
+  /**
+   * 新增空行
+   */
+  const AddNewRow = () => {
+    setTabeData(newTableData.concat([{
+      序号: { label: newTableData.length + 1 },
+      姓名: { label: "" },
+      性别: { label: "" },
+      年龄: { label: "" },
+      最后在线时间: { label: "" },
+    }]));
+  }
+
   return (
     <DataGrid
-      items={[
-        {
-          序号: { label: 1 },
-          姓名: { label: "陈丹", icon: <DocumentRegular /> },
-          性别: { label: "女", status: "available" },
-          年龄: { label: "18岁", timestamp: 1 },
-          最后在线时间: { label: "2024/11/6 13:50" },
-        },
-        {
-          序号: { label: 2 },
-          姓名: { label: "蔡青松", icon: <FolderRegular /> },
-          性别: { label: "男", status: "busy" },
-          年龄: { label: "30岁", timestamp: 2 },
-          最后在线时间: { label: "2024/11/6 13:51" },
-        },
-        {
-          序号: { label: 3 },
-          姓名: { label: "杨东明", icon: <VideoRegular /> },
-          性别: { label: "男", status: "away" },
-          年龄: { label: "25岁", timestamp: 2 },
-          最后在线时间: { label: "2024/11/6 13:52" },
-        },
-        {
-          序号: { label: 4 },
-          姓名: { label: "吴瑞强", icon: <DocumentPdfRegular /> },
-          性别: { label: "男", status: "offline" },
-          年龄: { label: "25岁", timestamp: 3 },
-          最后在线时间: { label: "2024/11/6 13:53" },
-        },
-      ]}
+      items={newTableData}
       columns={[
         createTableColumn({
-          columnId: "序号",
-          fixed: true,
+          columnId: "姓名",
           compare: (a, b) => {
-            return a.序号.label - b.序号.label;
+            return a.姓名.label.localeCompare(b.姓名.label);
           },
           renderHeaderCell: () => {
             return (
-              <TableCellLayout media={<NumberCircle116Regular />}>
-                序号
-                <HeaderMenuList dataType={DATA_TYPE.数字} title="序号" columnId="序号" />
+              <TableCellLayout media={<TextField16Regular />}>
+                姓名
+                <HeaderMenuList dataType={DATA_TYPE.文本} title="姓名" columnId="姓名" />
               </TableCellLayout>
             );
           },
           renderCell: (item) => {
-            return item.序号.label;
+            return <ChangeBtnShowType cellData={item.姓名.label} />
           },
         }),
         createTableColumn({
-          columnId: "姓名",
+          columnId: "序号",
+          fixed: true,
           compare: (a, b) => {
-            return a.姓名.label.localeCompare(b.姓名.label);
+            return a.序号.label - b.序号.label;
           },
           renderHeaderCell: () => {
             return (
-              <TableCellLayout media={<TextField16Regular />}>
-                姓名
-                <HeaderMenuList dataType={DATA_TYPE.文本} title="姓名" columnId="姓名" />
+              <TableCellLayout media={<NumberCircle116Regular />}>
+                序号
+                <HeaderMenuList dataType={DATA_TYPE.数字} title="序号" columnId="序号" />
               </TableCellLayout>
             );
           },
           renderCell: (item) => {
-            return <ChangeBtnShowType cellData={item.姓名.label} />
+            return editType.edit == "true" ? <Input type="number" defaultValue={item.序号.label} style={{ width: "100%" }} /> : item.序号.label;
           },
         }),
+
         createTableColumn({
           columnId: "性别",
           compare: (a, b) => {
@@ -299,7 +322,10 @@ const List = () => {
             );
           },
           renderCell: (item) => {
-            return item.性别.label;
+            return editType.edit == "true" ? <Select style={{ width: "calc(100% - 70px)" }}>
+              <option value="男" selected={item.性别.label == "男"}>男</option>
+              <option value="女" selected={item.性别.label == "女"}>女</option>
+            </Select> : item.性别.label;
           },
         }),
         createTableColumn({
@@ -334,11 +360,7 @@ const List = () => {
             );
           },
           renderCell: (item) => {
-            return (
-              <TableCellLayout media={item.最后在线时间.icon}>
-                {item.最后在线时间.label}
-              </TableCellLayout>
-            );
+            return editType.edit == "true" ? <Input type="date" defaultValue={item.最后在线时间.label} /> : item.最后在线时间.label;
           },
         }),
       ]}
@@ -347,7 +369,7 @@ const List = () => {
       sortState={dataSortType}
       subtleSelection
       resizableColumns
-      defaultSelectedItems={defaultSelectedItems}
+      // defaultSelectedItems={defaultSelectedItems}
       style={{ minWidth: "550px" }}
     >
       <DataGridHeader>
@@ -369,7 +391,18 @@ const List = () => {
           </DataGridRow>
         )}
       </DataGridBody>
+
+      <Button
+        appearance="subtle"
+        icon={<Add16Filled />}
+        style={{ color: "#ca5010" }}
+        onClick={() => {
+          AddNewRow();
+        }}
+      >添加新项目</Button>
     </DataGrid>
+
+
   );
 };
 

+ 1 - 1
src/router/index.js

@@ -20,7 +20,7 @@ const router = createBrowserRouter([
             },
             {
                 path: '/listnew',
-                element: <ListNew/>
+                element: <ListNew edit="true" />
             },
             {
                 path: '/tree',