Browse Source

platfrom presentation

main
hulei 3 weeks ago
parent
commit
e36cc6e024
20 changed files with 2600 additions and 0 deletions
  1. 130
    0
      ant-design-pro-vue3/src/views/front/platfrom/presentation/FocusCheck/Adorner/FocusAdorner.ts
  2. 71
    0
      ant-design-pro-vue3/src/views/front/platfrom/presentation/FocusCheck/Adorner/TipAdorner.ts
  3. 24
    0
      ant-design-pro-vue3/src/views/front/platfrom/presentation/FocusCheck/FieldPolicy/FieldPolicyCollection.ts
  4. 17
    0
      ant-design-pro-vue3/src/views/front/platfrom/presentation/FocusCheck/FieldPolicy/IFieldPolicy.ts
  5. 93
    0
      ant-design-pro-vue3/src/views/front/platfrom/presentation/FocusCheck/FieldPolicy/ShowTipPolicy.ts
  6. 183
    0
      ant-design-pro-vue3/src/views/front/platfrom/presentation/FocusManagers/FocusList.ts
  7. 575
    0
      ant-design-pro-vue3/src/views/front/platfrom/presentation/FocusManagers/FocusManager.ts
  8. 187
    0
      ant-design-pro-vue3/src/views/front/platfrom/presentation/FocusManagers/FocusManagerExt.ts
  9. 42
    0
      ant-design-pro-vue3/src/views/front/platfrom/presentation/Interfaces/Ipage.ts
  10. 21
    0
      ant-design-pro-vue3/src/views/front/platfrom/presentation/PageFunctions/PageClosedEventArgs.ts
  11. 265
    0
      ant-design-pro-vue3/src/views/front/platfrom/presentation/PageFunctions/PageContainer.ts
  12. 84
    0
      ant-design-pro-vue3/src/views/front/platfrom/presentation/PageFunctions/PageExtension.ts
  13. 175
    0
      ant-design-pro-vue3/src/views/front/platfrom/presentation/PageFunctions/PageFactory.ts
  14. 384
    0
      ant-design-pro-vue3/src/views/front/platfrom/presentation/PageFunctions/SprocketControl.ts
  15. 135
    0
      ant-design-pro-vue3/src/views/front/platfrom/presentation/PageFunctions/TradePage.ts
  16. 50
    0
      ant-design-pro-vue3/src/views/front/platfrom/presentation/PagesHelper/PageContainerHelper.ts
  17. 51
    0
      ant-design-pro-vue3/src/views/front/platfrom/presentation/PagesHelper/PageHelper.ts
  18. 8
    0
      ant-design-pro-vue3/src/views/front/platfrom/presentation/Themes/Generic.xaml
  19. 76
    0
      ant-design-pro-vue3/src/views/front/platfrom/presentation/Themes/PageContainer.Generic.xaml
  20. 29
    0
      ant-design-pro-vue3/src/views/front/platfrom/presentation/Themes/TradePage.Generic.xaml

+ 130
- 0
ant-design-pro-vue3/src/views/front/platfrom/presentation/FocusCheck/Adorner/FocusAdorner.ts View File

@@ -0,0 +1,130 @@
1
+// 模拟依赖属性和相关类型
2
+class DependencyProperty {
3
+    static Register(name: string, type: any, ownerType: any, metadata: any) {
4
+        return new DependencyProperty();
5
+    }
6
+}
7
+
8
+class FrameworkPropertyMetadata {
9
+    constructor(defaultValue: any) { }
10
+}
11
+
12
+class Brush { }
13
+class SolidColorBrush extends Brush { }
14
+class Pen {
15
+    constructor(brush: Brush, thickness: number) { }
16
+}
17
+class Colors {
18
+    static get Red() { return new SolidColorBrush(); }
19
+}
20
+
21
+class UIElement {
22
+    IsVisible: boolean = true;
23
+}
24
+
25
+class FrameworkElement extends UIElement {
26
+    RenderSize = { width: 0, height: 0 };
27
+}
28
+
29
+class DrawingContext {
30
+    constructor(private canvasContext: CanvasRenderingContext2D) { }
31
+
32
+    DrawLine(pen: Pen, startPoint: { x: number, y: number }, endPoint: { x: number, y: number }) {
33
+        this.canvasContext.beginPath();
34
+        this.canvasContext.moveTo(startPoint.x, startPoint.y);
35
+        this.canvasContext.lineTo(endPoint.x, endPoint.y);
36
+        this.canvasContext.stroke();
37
+    }
38
+}
39
+
40
+class Rect {
41
+    constructor(public size: { width: number, height: number }) { }//TODO 将height由0改为number
42
+
43
+    get TopLeft() { return { x: 0, y: 0 }; }
44
+    get TopRight() { return { x: this.size.width, y: 0 }; }
45
+    get BottomLeft() { return { x: 0, y: this.size.height }; }
46
+    get BottomRight() { return { x: this.size.width, y: this.size.height }; }
47
+}
48
+
49
+class Point {
50
+    constructor(public x: number, public y: number) { }
51
+}
52
+
53
+class Application {
54
+    static get Current() {
55
+        return {
56
+            TryFindResource(name: string) {
57
+                return null;
58
+            }
59
+        };
60
+    }
61
+}
62
+
63
+class Adorner {
64
+    constructor(public AdornedElement: FrameworkElement) { }
65
+    InvalidateVisual() { }
66
+}
67
+
68
+class FocusAdorner extends Adorner {
69
+    static FocusAdornerPen: Pen;
70
+
71
+    static BorderBrushProperty = DependencyProperty.Register("BorderBrush", Brush, FocusAdorner, new FrameworkPropertyMetadata(new SolidColorBrush()));
72
+    static BorderThicknessProperty = DependencyProperty.Register("BorderThickness", Number, FocusAdorner, new FrameworkPropertyMetadata(2));
73
+
74
+    get BorderBrush() { return null; }
75
+    set BorderBrush(value: Brush) { }
76
+
77
+    get BorderThickness() { return 2; }
78
+    set BorderThickness(value: number) { }
79
+
80
+    private _close: () => void;
81
+
82
+    constructor(adornedElement: FrameworkElement, private canvasContext: CanvasRenderingContext2D) {
83
+        super(adornedElement);
84
+        const dpd = {
85
+            AddValueChanged: (element: UIElement, handler: () => void) => { },
86
+            RemoveValueChanged: (element: UIElement, handler: () => void) => { }
87
+        };
88
+        const handler = () => {
89
+            this.InvalidateVisual();
90
+        };
91
+        dpd.AddValueChanged(adornedElement, handler);
92
+        this._close = () => {
93
+            dpd.RemoveValueChanged(adornedElement, handler);
94
+        };
95
+    }
96
+
97
+    static {
98
+        FocusAdorner.FocusAdornerPen = Application.Current.TryFindResource("FocusAdorner_Normal_Pen") as Pen;
99
+        if (!FocusAdorner.FocusAdornerPen) {
100
+            FocusAdorner.FocusAdornerPen = new Pen(new SolidColorBrush(), 1.0);
101
+        }
102
+    }
103
+
104
+    Close() {
105
+        this._close();
106
+    }
107
+
108
+    InvalidateVisual() {
109
+        const drawingContext = new DrawingContext(this.canvasContext);
110
+        this.OnRender(drawingContext);
111
+    }
112
+
113
+    protected OnRender(drawingContext: DrawingContext) {
114
+        if (!this.AdornedElement || !this.AdornedElement.IsVisible) return;
115
+
116
+        const adornedElementRect = new Rect(this.AdornedElement.RenderSize);
117
+
118
+        drawingContext.DrawLine(FocusAdorner.FocusAdornerPen, new Point(adornedElementRect.TopLeft.x - 3, adornedElementRect.TopLeft.y - 3), new Point(adornedElementRect.TopLeft.x + 5, adornedElementRect.TopLeft.y - 3));
119
+        drawingContext.DrawLine(FocusAdorner.FocusAdornerPen, new Point(adornedElementRect.TopLeft.x - 3, adornedElementRect.TopLeft.y - 3), new Point(adornedElementRect.TopLeft.x - 3, adornedElementRect.TopLeft.y + 5));
120
+
121
+        drawingContext.DrawLine(FocusAdorner.FocusAdornerPen, new Point(adornedElementRect.TopRight.x + 3, adornedElementRect.TopRight.y - 3), new Point(adornedElementRect.TopRight.x - 5, adornedElementRect.TopRight.y - 3));
122
+        drawingContext.DrawLine(FocusAdorner.FocusAdornerPen, new Point(adornedElementRect.TopRight.x + 3, adornedElementRect.TopRight.y - 3), new Point(adornedElementRect.TopRight.x + 3, adornedElementRect.TopRight.y + 5));
123
+
124
+        drawingContext.DrawLine(FocusAdorner.FocusAdornerPen, new Point(adornedElementRect.BottomLeft.x - 3, adornedElementRect.BottomLeft.y + 3), new Point(adornedElementRect.BottomLeft.x + 5, adornedElementRect.BottomLeft.y + 3));
125
+        drawingContext.DrawLine(FocusAdorner.FocusAdornerPen, new Point(adornedElementRect.BottomLeft.x - 3, adornedElementRect.BottomLeft.y + 3), new Point(adornedElementRect.BottomLeft.x - 3, adornedElementRect.BottomLeft.y - 5));
126
+
127
+        drawingContext.DrawLine(FocusAdorner.FocusAdornerPen, new Point(adornedElementRect.BottomRight.x + 3, adornedElementRect.BottomRight.y + 3), new Point(adornedElementRect.BottomRight.x - 5, adornedElementRect.BottomRight.y + 3));
128
+        drawingContext.DrawLine(FocusAdorner.FocusAdornerPen, new Point(adornedElementRect.BottomRight.x + 3, adornedElementRect.BottomRight.y + 3), new Point(adornedElementRect.BottomRight.x + 3, adornedElementRect.BottomRight.y - 5));
129
+    }
130
+}

+ 71
- 0
ant-design-pro-vue3/src/views/front/platfrom/presentation/FocusCheck/Adorner/TipAdorner.ts View File

@@ -0,0 +1,71 @@
1
+// 定义枚举
2
+export enum TipAdornerPlacement {
3
+    Bottom,
4
+    Right,
5
+}
6
+
7
+// 定义 TipAdorner 类
8
+export class TipAdorner {
9
+    private messageHost: HTMLElement;
10
+    private adornedElement: HTMLElement;
11
+    private adornerLayer: HTMLElement;
12
+    private message: string;
13
+    private messageTemplate: string | null = null;
14
+    private placement: TipAdornerPlacement = TipAdornerPlacement.Bottom;
15
+
16
+    constructor(adornedElement: HTMLElement, adornerLayer: HTMLElement) {
17
+        this.adornedElement = adornedElement;
18
+        this.adornerLayer = adornerLayer;
19
+        this.messageHost = document.createElement('div');
20
+        this.adornerLayer.appendChild(this.messageHost);
21
+    }
22
+
23
+    public set Message(value: string) {
24
+        this.message = value;
25
+        this.messageHost.textContent = value;
26
+    }
27
+
28
+    public get Message(): string {
29
+        return this.message;
30
+    }
31
+
32
+    public set MessageTemplate(value: string | null) {
33
+        this.messageTemplate = value;
34
+        if (value) {
35
+            this.messageHost.innerHTML = value;
36
+        }
37
+    }
38
+
39
+    public get MessageTemplate(): string | null {
40
+        return this.messageTemplate;
41
+    }
42
+
43
+    public set Placement(value: TipAdornerPlacement) {
44
+        this.placement = value;
45
+        this.arrange();
46
+    }
47
+
48
+    public get Placement(): TipAdornerPlacement {
49
+        return this.placement;
50
+    }
51
+
52
+    private arrange() {
53
+        const adornedRect = this.adornedElement.getBoundingClientRect();
54
+        const messageHostRect = this.messageHost.getBoundingClientRect();
55
+
56
+        let x = 0;
57
+        let y = 0;
58
+
59
+        if (this.placement === TipAdornerPlacement.Right) {
60
+            x = adornedRect.right;
61
+            y = adornedRect.top;
62
+        } else {
63
+            x = adornedRect.left;
64
+            y = adornedRect.bottom;
65
+        }
66
+
67
+        this.messageHost.style.position = 'absolute';
68
+        this.messageHost.style.left = `${x}px`;
69
+        this.messageHost.style.top = `${y}px`;
70
+    }
71
+}

+ 24
- 0
ant-design-pro-vue3/src/views/front/platfrom/presentation/FocusCheck/FieldPolicy/FieldPolicyCollection.ts View File

@@ -0,0 +1,24 @@
1
+// 假设 IFieldPolicy 接口的基本结构
2
+export interface IFieldPolicy {
3
+    // 这里可以根据实际情况添加更多属性和方法
4
+}
5
+
6
+// 实现 FieldPolicyCollection 类
7
+export class FieldPolicyCollection {
8
+    private items: IFieldPolicy[] = [];
9
+
10
+    // 添加元素到集合
11
+    add(item: IFieldPolicy): void {
12
+        this.items.push(item);
13
+    }
14
+
15
+    // 获取集合中元素的数量
16
+    get count(): number {
17
+        return this.items.length;
18
+    }
19
+
20
+    // 根据索引获取元素
21
+    getItem(index: number): IFieldPolicy | undefined {
22
+        return this.items[index];
23
+    }
24
+}

+ 17
- 0
ant-design-pro-vue3/src/views/front/platfrom/presentation/FocusCheck/FieldPolicy/IFieldPolicy.ts View File

@@ -0,0 +1,17 @@
1
+// 模拟 ICloneable 接口
2
+interface ICloneable {
3
+    clone(): any;
4
+}
5
+
6
+// 定义一个通用的对象类型,模拟 DependencyObject
7
+type DependencyObject = Record<string, any>;
8
+
9
+// 定义 IFieldPolicy 接口
10
+export interface IFieldPolicy extends ICloneable {
11
+    /**
12
+     * 执行校验策略
13
+     * @param sender 触发操作的对象
14
+     * @param content 与校验相关的内容
15
+     */
16
+    Run(sender: DependencyObject, content: any): void;
17
+}

+ 93
- 0
ant-design-pro-vue3/src/views/front/platfrom/presentation/FocusCheck/FieldPolicy/ShowTipPolicy.ts View File

@@ -0,0 +1,93 @@
1
+// 模拟 IFieldPolicy 接口
2
+interface IFieldPolicy {
3
+    Run(sender: HTMLElement, content: any): void;
4
+    Clone(): any;
5
+}
6
+
7
+// 模拟 TipAdornerPlacement 类型
8
+type TipAdornerPlacement = string;
9
+
10
+// 模拟 TipAdorner 类
11
+class TipAdorner {
12
+    Placement: TipAdornerPlacement;
13
+    Message: string;
14
+    element: HTMLElement;
15
+
16
+    constructor(element: HTMLElement, _adornerLayer: any) {
17
+        this.element = element;
18
+    }
19
+}
20
+
21
+// 模拟 AdornerLayer 类
22
+class AdornerLayer {
23
+    private adorners: any[] = [];
24
+
25
+    static GetAdornerLayer(element: HTMLElement): AdornerLayer {
26
+        return new AdornerLayer();
27
+    }
28
+
29
+    GetAdorners(element: HTMLElement): any[] {
30
+        return this.adorners.filter(ad => ad.element === element);
31
+    }
32
+
33
+    Add(adorner: any) {
34
+        this.adorners.push(adorner);
35
+    }
36
+
37
+    Remove(adorner: any) {
38
+        const index = this.adorners.indexOf(adorner);
39
+        if (index !== -1) {
40
+            this.adorners.splice(index, 1);
41
+        }
42
+    }
43
+}
44
+
45
+export class ShowTipPolicy implements IFieldPolicy {
46
+    private _adorner: TipAdorner | null = null;
47
+    Placement: TipAdornerPlacement;
48
+
49
+    Run(sender: HTMLElement, content: any): void {
50
+        const element = sender;
51
+        if (!element) return;
52
+
53
+        const adornerLayer = AdornerLayer.GetAdornerLayer(element);
54
+        if (adornerLayer) {
55
+            const adorners = adornerLayer.GetAdorners(element);
56
+            if (adorners) {
57
+                adorners.forEach(ad => {
58
+                    if (ad instanceof TipAdorner) {
59
+                        adornerLayer.Remove(ad);
60
+                    }
61
+                });
62
+            }
63
+
64
+            this._adorner = new TipAdorner(element, adornerLayer);
65
+            this._adorner.Placement = this.Placement;
66
+            this._adorner.Message = content === null ? "输入错误" : content.toString();
67
+            adornerLayer.Add(this._adorner);
68
+
69
+            element.addEventListener('blur', this.OnLostFocus.bind(this));
70
+
71
+            if (element.tagName === 'INPUT') {// && element.type === 'text' TODO报错暂时注掉
72
+                (element as HTMLInputElement).select();
73
+            }
74
+        }
75
+    }
76
+
77
+    private OnLostFocus(e: Event) {
78
+        const element = e.target as HTMLElement;
79
+        if (!element) return;
80
+
81
+        element.removeEventListener('blur', this.OnLostFocus.bind(this));
82
+
83
+        const adornerLayer = AdornerLayer.GetAdornerLayer(element);
84
+        if (!adornerLayer || !this._adorner) return;
85
+
86
+        adornerLayer.Remove(this._adorner);
87
+        this._adorner = null;
88
+    }
89
+
90
+    Clone(): any {
91
+        throw new Error('方法未实现');
92
+    }
93
+}

+ 183
- 0
ant-design-pro-vue3/src/views/front/platfrom/presentation/FocusManagers/FocusList.ts View File

@@ -0,0 +1,183 @@
1
+// 模拟 WPF 相关类
2
+class FrameworkElement {
3
+    visibility: 'Visible' | 'Hidden' | 'Collapsed' = 'Visible';
4
+    actualHeight: number = 0;
5
+    actualWidth: number = 0;
6
+    tabIndex: number = 0;
7
+
8
+    constructor(public x: number, public y: number) { }
9
+
10
+    translatePoint(point: { x: number, y: number }, root: FrameworkElement): { x: number, y: number } {
11
+        return { x: this.x + point.x, y: this.y + point.y };
12
+    }
13
+}
14
+
15
+class ScrollViewer extends FrameworkElement { }
16
+
17
+// 模拟 Platform.Common 中的方法
18
+class VisualTreeHelper {
19
+    static getChildrenCount(element: FrameworkElement): number {
20
+        // 模拟实现,实际需要根据具体情况实现
21
+        return 0;
22
+    }
23
+
24
+    static getChild(element: FrameworkElement, index: number): FrameworkElement | null {
25
+        // 模拟实现,实际需要根据具体情况实现
26
+        return null;
27
+    }
28
+}
29
+
30
+class FocusManager {
31
+    static getOnlyMouseControlHandled(element: FrameworkElement): any | null {
32
+        // 模拟实现,实际需要根据具体情况实现
33
+        return null;
34
+    }
35
+
36
+    static getIsInternalKeyboardControlling(element: FrameworkElement): boolean {
37
+        // 模拟实现,实际需要根据具体情况实现
38
+        return true;
39
+    }
40
+}
41
+
42
+// 扩展 FrameworkElement 类以模拟 FindVisualTreeAncestor 方法
43
+interface FrameworkElement {
44
+    findVisualTreeAncestor(handle: (element: any) => boolean): any | null;
45
+}
46
+
47
+FrameworkElement.prototype.findVisualTreeAncestor = function (handle: (element: any) => boolean): any | null {
48
+    let current: any = this;
49
+    while (current) {
50
+        if (handle(current)) {
51
+            return current;
52
+        }
53
+        // 模拟父元素,实际需要根据具体情况实现
54
+        current = null;
55
+    }
56
+    return null;
57
+};
58
+
59
+export default class FocusList implements Iterable<FrameworkElement> {
60
+    private _internalList: FrameworkElement[] = [];
61
+    private _rootElement: FrameworkElement;
62
+    private stackOperatorVisible: FrameworkElement[] = [];
63
+
64
+    private constructor(rootElement: FrameworkElement) {
65
+        this._rootElement = rootElement;
66
+        this.refresh();
67
+    }
68
+
69
+    static create(rootElement: FrameworkElement): FocusList {
70
+        return new FocusList(rootElement);
71
+    }
72
+
73
+    private compareByLocation(targetElement: FrameworkElement, currentElement: FrameworkElement): boolean {
74
+        const handle = (x: any) => x instanceof ScrollViewer;
75
+        const targetScrollViewer = targetElement.findVisualTreeAncestor(handle) as ScrollViewer | null;
76
+        const currentScrollViewer = currentElement.findVisualTreeAncestor(handle) as ScrollViewer | null;
77
+
78
+        if (targetScrollViewer && currentScrollViewer && targetScrollViewer !== currentScrollViewer) {
79
+            if (true) {//TODD焦点的控制涉及到FrameworkElement targetScrollViewer.isAncestorOf(currentScrollViewer) 缺少方法isAncestorOf
80
+                currentElement = currentScrollViewer;
81
+            } else {
82
+                targetElement = targetScrollViewer;
83
+            }
84
+        } else if (!targetScrollViewer || !currentScrollViewer || targetScrollViewer !== currentScrollViewer) {
85
+            if (targetScrollViewer) targetElement = targetScrollViewer;
86
+            if (currentScrollViewer) currentElement = currentScrollViewer;
87
+        }
88
+
89
+        const locationPoint = { x: 0, y: 0 };
90
+        const targetElementOffset = targetElement.translatePoint(locationPoint, this._rootElement);
91
+        const currentElementOffset = currentElement.translatePoint(locationPoint, this._rootElement);
92
+
93
+        if (targetElementOffset.y + targetElement.actualHeight <= currentElementOffset.y + currentElement.actualHeight / 2) {
94
+            return true;
95
+        }
96
+
97
+        return targetElementOffset.x <= currentElementOffset.x &&
98
+            targetElementOffset.y <= currentElementOffset.y + currentElement.actualHeight / 2;
99
+    }
100
+
101
+    private getFocusChildren(rootElement: FrameworkElement) {
102
+        if (!rootElement) return;
103
+
104
+        if (rootElement.visibility === 'Collapsed') {
105
+            this.stackOperatorVisible.push(rootElement);
106
+            rootElement.visibility = 'Hidden';
107
+            // 模拟 UpdateLayout 方法
108
+            // rootElement.updateLayout();
109
+        }
110
+
111
+        const childrenCount = VisualTreeHelper.getChildrenCount(rootElement);
112
+        for (let i = 0; i < childrenCount; i++) {
113
+            const child = VisualTreeHelper.getChild(rootElement, i) as FrameworkElement | null;
114
+            if (!child) continue;
115
+
116
+            if (FocusManager.getOnlyMouseControlHandled(child) !== null) continue;
117
+
118
+            if (!FocusManager.getIsInternalKeyboardControlling(child)) {
119
+                this.getFocusChildren(child);
120
+            } else {
121
+                if (child.visibility === 'Collapsed') {
122
+                    this.stackOperatorVisible.push(child);
123
+                    child.visibility = 'Visible';
124
+                    // 模拟 UpdateLayout 方法
125
+                    // rootElement.updateLayout();
126
+                }
127
+
128
+                const insertIndex = this.getInsertIndex(child);
129
+                this._internalList.splice(insertIndex, 0, child);
130
+            }
131
+        }
132
+    }
133
+
134
+    private getInsertIndex(targetElement: FrameworkElement): number {
135
+        let currentIndex = this._internalList.length - 1;
136
+
137
+        while (currentIndex > -1) {
138
+            const currentElement = this._internalList[currentIndex];
139
+            if (targetElement.tabIndex === currentElement.tabIndex) {
140
+                if (!this.compareByLocation(targetElement, currentElement)) {
141
+                    return currentIndex + 1;
142
+                }
143
+            } else if (targetElement.tabIndex > currentElement.tabIndex) {
144
+                return currentIndex + 1;
145
+            } else if (!this.compareByLocation(targetElement, currentElement)) {
146
+                return currentIndex + 1;
147
+            }
148
+            currentIndex--;
149
+        }
150
+        return currentIndex > -1 ? currentIndex : 0;
151
+    }
152
+
153
+    refresh() {
154
+        // 模拟 IsVisible 和 IsLoaded 属性
155
+        if (true) {
156
+            this._internalList = [];
157
+            this.stackOperatorVisible = [];
158
+            this.getFocusChildren(this._rootElement);
159
+
160
+            this.stackOperatorVisible.forEach((current) => {
161
+                current.visibility = 'Collapsed';
162
+            });
163
+        }
164
+    }
165
+
166
+    get count(): number {
167
+        return this._internalList.length;
168
+    }
169
+
170
+    get(index: number): FrameworkElement {
171
+        return this._internalList[index];
172
+    }
173
+
174
+    indexOf(element: FrameworkElement): number {
175
+        return this._internalList.indexOf(element);
176
+    }
177
+
178
+    [Symbol.iterator](): Iterator<FrameworkElement> {
179
+        return this._internalList[Symbol.iterator]();
180
+    }
181
+}
182
+
183
+export { FocusList, FrameworkElement };

+ 575
- 0
ant-design-pro-vue3/src/views/front/platfrom/presentation/FocusManagers/FocusManager.ts View File

@@ -0,0 +1,575 @@
1
+
2
+import FocusList from "./FocusList";
3
+
4
+// 模拟 WPF 部分类型
5
+interface DependencyObject {
6
+    // 可根据实际情况添加更多属性和方法
7
+}
8
+//微软系统框架 需要重新实现TODO
9
+interface FrameworkElement extends DependencyObject {
10
+    // Focus(): boolean;
11
+    // IsEnabled: boolean;
12
+    // IsVisible: boolean;
13
+    // Focusable: boolean;
14
+    // 可根据实际情况添加更多属性和方法
15
+}
16
+
17
+interface RoutedEventArgs {
18
+    Handled: boolean;
19
+    Source: any;
20
+    OriginalSource: any;
21
+}
22
+
23
+interface KeyEventArgs extends RoutedEventArgs {
24
+    Key: string;
25
+}
26
+
27
+interface MouseEventArgs extends RoutedEventArgs {
28
+    // 可根据实际情况添加更多属性和方法
29
+}
30
+
31
+// 模拟自定义类型
32
+
33
+
34
+interface FocusAdorner {
35
+    Close(): void;
36
+}
37
+
38
+interface AdornerLayer {
39
+    Remove(adorner: FocusAdorner): void;
40
+    Add(adorner: FocusAdorner): void;
41
+}
42
+
43
+interface TradePage extends FrameworkElement {
44
+    Ready: (sender: any, e: any) => void;
45
+}
46
+
47
+
48
+enum FocusNavigation {
49
+    Top,
50
+    Backward,
51
+    Forward
52
+}
53
+
54
+enum FocusHandledResult {
55
+    Self,
56
+    Forward,
57
+    Backward,
58
+    System
59
+}
60
+
61
+// 模拟附加属性存储
62
+const attachedProperties = new WeakMap<DependencyObject, { [key: string]: any }>();
63
+
64
+function getAttachedProperty(obj: DependencyObject, propertyName: string): any {
65
+    const props = attachedProperties.get(obj);
66
+    return props ? props[propertyName] : undefined;
67
+}
68
+
69
+function setAttachedProperty(obj: DependencyObject, propertyName: string, value: any) {
70
+    let props = attachedProperties.get(obj);
71
+    if (!props) {
72
+        props = {};
73
+        attachedProperties.set(obj, props);
74
+    }
75
+    props[propertyName] = value;
76
+}
77
+
78
+export default class FocusManager {
79
+    private _preAdorder: FocusAdorner | null = null;
80
+    private _focusAdornerLayer: AdornerLayer | null = null;
81
+    public IsFocusContinue: boolean = false;
82
+    private readonly _target: FrameworkElement;
83
+    public _focusList: FocusList | null = null;
84
+    private _currentFocusedElement: FrameworkElement | null = null;
85
+    private static readonly DEFAULT_BUTTON_CLICK_TICK_OUT = -1;
86
+    private _canAcceptUserInput = true;
87
+    private _isOperator = false;
88
+
89
+    get CurrentFocusedElement(): FrameworkElement | null {
90
+        return this._currentFocusedElement;
91
+    }
92
+
93
+    private set CurrentFocusedElement(value: FrameworkElement | null) {
94
+        if (value) {
95
+            if (!this._focusAdornerLayer) {
96
+                // 模拟获取装饰器层
97
+                this._focusAdornerLayer = {} as AdornerLayer;
98
+            }
99
+
100
+            if (this._preAdorder) {
101
+                this._focusAdornerLayer.Remove(this._preAdorder);
102
+                this._preAdorder.Close();
103
+            }
104
+
105
+            if (getAttachedProperty(value, "IsFocusAdorner")) {
106
+                this._preAdorder = {} as FocusAdorner;
107
+                this._focusAdornerLayer.Add(this._preAdorder);
108
+            }
109
+        }
110
+        if (this._currentFocusedElement !== value) {
111
+            this._currentFocusedElement = value;
112
+        }
113
+    }
114
+
115
+    get CanAcceptUserInput(): boolean {
116
+        return this._canAcceptUserInput;
117
+    }
118
+
119
+    set CanAcceptUserInput(value: boolean) {
120
+        this._canAcceptUserInput = value;
121
+    }
122
+
123
+    set CanFocusAdjustly(value: boolean) {
124
+        // 模拟移除和添加事件处理程序
125
+        if (!value) {
126
+            // 移除 LayoutUpdated 事件处理程序
127
+        } else {
128
+            // 添加 LayoutUpdated 事件处理程序
129
+        }
130
+    }
131
+
132
+    private constructor(target: FrameworkElement) {
133
+        this._target = target;
134
+        // 模拟 IsVisibleChanged 事件
135
+        // target.IsVisibleChanged += (sender, e) => { ... };
136
+    }
137
+
138
+    get IsOperator(): boolean {
139
+        if (this._isOperator) return this._isOperator;
140
+
141
+        if (FocusList && this._currentFocusedElement) {
142
+            // const ind = this._focusList.indexOf(this._currentFocusedElement | null);//FrameworkElement内容需要改
143
+            // if (ind === 0 && this._currentFocusedElement instanceof TextBox) {
144
+            //     const txt = this._currentFocusedElement as TextBox;
145
+            //     this._isOperator = txt.Text.length !== 0;
146
+            // }
147
+        }
148
+
149
+        return this._isOperator;
150
+    }
151
+
152
+    // 附加属性相关方法
153
+    static GetCanSkipPreviousFocus(d: DependencyObject): boolean {
154
+        return getAttachedProperty(d, "CanSkipPreviousFocus") || false;
155
+    }
156
+
157
+    static SetCanSkipPreviousFocus(d: DependencyObject, value: boolean) {
158
+        setAttachedProperty(d, "CanSkipPreviousFocus", value);
159
+    }
160
+
161
+    // 其他附加属性方法类似实现...
162
+
163
+    private Registe() {
164
+        const tmp = this._target as TradePage;
165
+        if (tmp) {
166
+            // tmp.Ready += this._target_Ready.bind(this);
167
+        }
168
+
169
+        // 模拟注册事件
170
+        // this._target.PreviewKeyDown += this.OnPreviewKeyDown.bind(this);
171
+        // this._target.PreviewMouseDown += this.OnPreviewMouseDown.bind(this);
172
+        // this._target.LayoutUpdated += this._target_LayoutUpdated.bind(this);
173
+    }
174
+
175
+    private _target_Ready(sender: any, e: any) {
176
+        const tmp = this._target as TradePage;
177
+        if (tmp) {
178
+            // tmp.Ready -= this._target_Ready.bind(this);
179
+        }
180
+
181
+        // this._focusList = FocusList.create(this._target);//TODO FrameworkElement 焦点控制先注释
182
+
183
+        if (!this._focusAdornerLayer) {
184
+            this._focusAdornerLayer = {} as AdornerLayer;
185
+        }
186
+
187
+        if (this._focusList) {
188
+            // for (let i = 0; i < this._focusList.Count; i++) {
189
+            //     const item = this._focusList[i];
190
+            //     // FocusManager.SetManagerInstance(item, this);
191
+            // }
192
+        }
193
+
194
+        this.ReSetFocus();
195
+    }
196
+
197
+    private _target_LayoutUpdated(sender: any, e: any) {
198
+        // 模拟获取窗口
199
+        const win = null;
200
+        if (!win || !win.IsActive) return;
201
+
202
+        if (this._currentFocusedElement && (getAttachedProperty(this._target, "AutoFocus"))) {
203
+            this.CurrentFocusedElement = this._currentFocusedElement;
204
+        }
205
+        //TODO  || this._target.IsMouseOver) &&!this._target.IsKeyboardFocusWithin && this._currentFocusedElement.Focus() //TODO 没有FrameworkElement IsMouseOver方法
206
+        // if (this._currentFocusedElement &&
207
+        //     this._currentFocusedElement.IsFocused &&
208
+        //     !this.IsEnableFocus(this._currentFocusedElement) &&
209
+        //     !this._currentFocusedElement.IsEnabled &&
210
+        //     this._currentFocusedElement.IsVisible) {
211
+        //     this.CurrentFocusedElement = this._currentFocusedElement;
212
+        //     this.MoveFocusHost(FocusNavigation.Forward);
213
+        // }
214
+    }
215
+
216
+    private UnRegiste() {
217
+        // 模拟移除事件处理程序
218
+        // this._target.PreviewKeyDown -= this.OnPreviewKeyDown.bind(this);
219
+        // this._target.PreviewMouseDown -= this.OnPreviewMouseDown.bind(this);
220
+        // this._target.LayoutUpdated -= this._target_LayoutUpdated.bind(this);
221
+
222
+        // FocusManager.SetManagerInstance(this._target, null);
223
+    }
224
+
225
+    public ReSetFocus() {
226
+        this.MoveFocusHost(FocusNavigation.Top);
227
+    }
228
+
229
+    public SetFocus(target: FrameworkElement) {
230
+        if (!target) throw new Error("element 不能为 null");
231
+        //TODD焦点的控制涉及到FrameworkElement
232
+        // // 模拟 UIInvoke
233
+        // if (this._currentFocusedElement !== target &&
234
+        //     this.RaiseFocusManagerEvent(target, "PreviewGotFocusEvent") &&
235
+        //     this.RaiseFocusManagerEvent(target, "GotFocusEvent") &&
236
+        //     target.Focus()) {
237
+        //     this.CurrentFocusedElement = target;
238
+        // } else if (this._currentFocusedElement) {
239
+        //     this._currentFocusedElement.Focus();
240
+        // } else {
241
+        //     this.ReSetFocus();
242
+        // }
243
+    }
244
+
245
+    public MoveFocus(navigation: FocusNavigation, isRaiseEvent = true): boolean {
246
+        if (isRaiseEvent) {
247
+            return this.MoveFocusHost(navigation) ?? false;
248
+        } else {
249
+            let targetElement = this._currentFocusedElement;
250
+            if (this._focusList && targetElement) {
251
+                const index = 100;// this._focusList.IndexOf(targetElement);//TODO
252
+                switch (navigation) {
253
+                    case FocusNavigation.Top:
254
+                        this.ReSetFocus();
255
+                        break;
256
+                    case FocusNavigation.Backward:
257
+                        const ind = index > 0 ? index - 1 : 0;
258
+                        targetElement = this._focusList[ind];
259
+                        break;
260
+                    case FocusNavigation.Forward:
261
+                        targetElement = this._focusList[(index + 1) % this._focusList.count];
262
+                        break;
263
+                }
264
+
265
+                if (targetElement && targetElement !== this._currentFocusedElement) {
266
+                    this.SetFocus(targetElement);
267
+                    return true;
268
+                }
269
+            }
270
+            return false;
271
+        }
272
+    }
273
+
274
+    public Refresh() {
275
+        if (this._focusList) {
276
+            this._focusList.refresh();
277
+        }
278
+    }
279
+
280
+    private OnPreviewMouseDown(sender: any, e: RoutedEventArgs) {
281
+        if (this._target !== sender) return;
282
+        if (!this.CanAcceptUserInput) {
283
+            e.Handled = true;
284
+            return;
285
+        }
286
+
287
+        let clickedElement = e.Source as FrameworkElement;
288
+        let originalElement = e.Source as FrameworkElement;
289
+
290
+        if (!clickedElement) return;
291
+
292
+        if (!getAttachedProperty(clickedElement, "OnlyMouseControlHandled") &&
293
+            !getAttachedProperty(clickedElement, "IsInternalKeyboardControlling")) {
294
+            let originalSourceElement = e.OriginalSource as FrameworkElement;
295
+            if (originalSourceElement) {
296
+                if (getAttachedProperty(originalSourceElement, "OnlyMouseControlHandled") ||
297
+                    getAttachedProperty(originalSourceElement, "IsInternalKeyboardControlling")) {
298
+                    clickedElement = originalSourceElement;
299
+                } else {
300
+                    // 模拟 FindVisualTreeAncestor
301
+                    // if (originalSourceElement.FindVisualTreeAncestor(x => x is Window) == null) { ... }
302
+                    // clickedElement = originalSourceElement.FindVisualTreeAncestor(d => ...);
303
+                }
304
+            }
305
+        }
306
+
307
+        // if (!clickedElement || clickedElement instanceof IPage) {
308
+        //     e.Handled = true;
309
+        //     return;
310
+        // }
311
+
312
+        const handled = getAttachedProperty(clickedElement, "OnlyMouseControlHandled");
313
+        if (handled) {
314
+            let flag = false;
315
+            // 模拟判断条件
316
+            // if (originalElement is ScrollViewer || ...) { ... }
317
+            // const focusElements = originalElement.FindVisualTreeChildren();
318
+            // if (focusElements.Contains(this._currentFocusedElement)) { ... }
319
+
320
+            if (flag) {
321
+                handled(clickedElement, e);
322
+                return;
323
+            }
324
+        }
325
+
326
+        if (this._focusList && this._currentFocusedElement) {
327
+            // const currentIndex = this._focusList.IndexOf(this._currentFocusedElement);
328
+            // let targetIndex = this._focusList.IndexOf(clickedElement);
329
+
330
+            // if (targetIndex < 0) {
331
+            //     while (true) {
332
+            //         clickedElement = LogicalTreeHelper.GetParent(clickedElement) as FrameworkElement;
333
+            //         if (!clickedElement || clickedElement instanceof IPage) {
334
+            //             e.Handled = true;
335
+            //             return;
336
+            //         }
337
+            //         targetIndex = this._focusList.IndexOf(clickedElement);
338
+            //         if (targetIndex >= 0) break;
339
+            //     }
340
+            // }
341
+
342
+            // if (currentIndex === targetIndex) {
343
+            //     if (this.ButtonClickTick(this._currentFocusedElement)) {
344
+            //         e.Handled = true;
345
+            //     }
346
+
347
+            //     const funcFocusHandled = getAttachedProperty(this._currentFocusedElement, "MouseFocusHandled");
348
+            //     if (funcFocusHandled) {
349
+            //         const result = funcFocusHandled(this._currentFocusedElement, e as MouseEventArgs);
350
+            //         // 处理结果
351
+            //     }
352
+            //     return;
353
+            // }
354
+
355
+            //   const result = this.MoveFocusHost(targetIndex > currentIndex ? FocusNavigation.Forward : FocusNavigation.Backward, clickedElement);
356
+            if (result === false) {
357
+                e.Handled = true;
358
+            } else if (!this._isOperator) {
359
+                this._isOperator = true;
360
+            }
361
+        }
362
+    }
363
+
364
+    private OnPreviewKeyDown(sender: any, e: KeyEventArgs) {
365
+        if (this._target !== sender) return;
366
+        if (!this.CanAcceptUserInput) {
367
+            e.Handled = true;
368
+            return;
369
+        }
370
+        if (!this._currentFocusedElement) return;
371
+
372
+        if (this._currentFocusedElement instanceof ButtonBase && (e.Key === "Enter" || e.Key === "Space")) {
373
+            if (this.ButtonClickTick(this._currentFocusedElement)) {
374
+                e.Handled = true;
375
+            }
376
+        }
377
+
378
+        const funcFocusHandled = getAttachedProperty(this._currentFocusedElement, "FocusHandled");
379
+        if (funcFocusHandled) {
380
+            const pressKey = HotKeyHelper.GetKeyName(e.Key);
381
+            const result = funcFocusHandled(this._currentFocusedElement, e);
382
+            // 处理结果
383
+        }
384
+
385
+        let pressKey = "";
386
+        // 模拟按键判断
387
+        // if (e.Key == Key.Up || ...) { ... }
388
+
389
+        let result: boolean | null = true;
390
+        if (pressKey === "DOWN") {
391
+            e.Handled = true;
392
+            result = this.MoveFocusHost(FocusNavigation.Forward);
393
+            if (!this._isOperator) this._isOperator = true;
394
+        } else if (pressKey === "UP") {
395
+            e.Handled = true;
396
+            result = this.MoveFocusHost(FocusNavigation.Backward);
397
+            if (!this._isOperator) this._isOperator = true;
398
+        }
399
+
400
+        if (result === false) {
401
+            e.Handled = true;
402
+        }
403
+    }
404
+
405
+    private ButtonClickTick(clickElement: FrameworkElement): boolean {
406
+        const clickTick = getAttachedProperty(clickElement, "ButtonClickTick") || 0;
407
+        const clickTickOut = getAttachedProperty(clickElement, "ButtonClickTickOut") || FocusManager.DEFAULT_BUTTON_CLICK_TICK_OUT;
408
+
409
+        if (clickTick === 0) {
410
+            setAttachedProperty(clickElement, "ButtonClickTick", Date.now());
411
+        } else {
412
+            const tLeft = (Date.now() - clickTick) / 1000;
413
+            if (tLeft <= clickTickOut) {
414
+                return true;
415
+            } else {
416
+                setAttachedProperty(clickElement, "ButtonClickTick", Date.now());
417
+            }
418
+        }
419
+
420
+        return false;
421
+    }
422
+
423
+    private RaiseFocusManagerEvent(target: DependencyObject, routedEvent: string): boolean {
424
+        this.IsFocusContinue = true;
425
+        if (!target) return false;
426
+        // 模拟事件触发
427
+        return this.IsFocusContinue;
428
+    }
429
+
430
+    private MoveFocusHost(navigation: FocusNavigation = FocusNavigation.Forward, target: FrameworkElement | null = null): boolean | null {
431
+        if (!this._focusList) {
432
+            //  this._focusList = FocusList.create(this._target);
433
+        }
434
+
435
+        let currentElement = this._currentFocusedElement;
436
+        let targetElement: FrameworkElement | null = null;
437
+
438
+        //         if (this._focusList) {
439
+        //             for (let i = 0; i < this._focusList.count; i++) {
440
+        //                 // if (!currentElement || !this._focusList.contains(currentElement)) {
441
+        //                 //     navigation = FocusNavigation.Top;
442
+        //                 // }
443
+
444
+        //                 if (this._focusList && currentElement) {
445
+        //                     // // const index = this._focusList.IndexOf(currentElement);
446
+        //                     // switch (navigation) {
447
+        //                     //     case FocusNavigation.Top:
448
+        //                     //         targetElement = this._focusList[i];
449
+        //                     //         break;
450
+        //                     //     case FocusNavigation.Backward:
451
+        //                     //         const ind = index > 0 ? index - 1 : 0;
452
+        //                     //         targetElement = this._focusList[ind];
453
+        //                     //         break;
454
+        //                     //     case FocusNavigation.Forward:
455
+        //                     //         targetElement = this._focusList[(index + 1) % this._focusList.Count];
456
+        //                     //         break;
457
+        //                     //     default:
458
+        //                     //         throw new Error("MoveFocus:无效的参数!");
459
+        //                     // }
460
+        //                 }
461
+
462
+        //                 if (!targetElement) return false;
463
+        //                 if (targetElement === currentElement) return null;
464
+
465
+        //                 if (navigation !== FocusNavigation.Forward) {
466
+        //                     // const tmpTarget = target || targetElement;
467
+        //                     // if (this.IsEnableFocus(tmpTarget)) {
468
+        //                     //     tmpTarget.Focus();
469
+        //                     //     if (this.RaiseFocusManagerEvent(tmpTarget, "PreviewGotFocusEvent") &&
470
+        //                     //         this.RaiseFocusManagerEvent(tmpTarget, "GotFocusEvent")) {
471
+        //                     //         this.CurrentFocusedElement = tmpTarget;
472
+        //                     //         if (tmpTarget instanceof ButtonBase && navigation !== FocusNavigation.Top) {
473
+        //                     //             return !this.ButtonClickTick(tmpTarget);
474
+        //                     //         }
475
+        //                     //         return true;
476
+        //                     //     } else {
477
+        //                     //         return false;
478
+        //                     //     }
479
+        //                     // } else if (!target) {
480
+        //                     //     // currentElement = tmpTarget;
481
+        //                     // }
482
+        //                     // continue;
483
+        //                 } else {
484
+        //                     return false;
485
+        //                 }
486
+        //             } else if (target && FocusManager.GetCanSkipPreviousFocus(target)) {
487
+        //                 targetElement = target;
488
+        //             } else {
489
+        //                 if (currentElement &&
490
+        //                     this.IsEnableFocus(currentElement) &&
491
+        //                     (!this.RaiseFocusManagerEvent(currentElement, "PreviewLostFocusEvent") ||
492
+        //                         !this.RaiseFocusManagerEvent(currentElement, "LostFocusEvent"))) {
493
+        //                     return false;
494
+        //                 }
495
+        //             }
496
+
497
+        //             if (this.IsEnableFocus(targetElement)) {
498
+        //                 targetElement.Focus();
499
+        //                 if (this.RaiseFocusManagerEvent(targetElement, "PreviewGotFocusEvent") &&
500
+        //                     this.RaiseFocusManagerEvent(targetElement, "GotFocusEvent")) {
501
+        //                     this.CurrentFocusedElement = targetElement;
502
+        //                 } else {
503
+        //                     return false;
504
+        //                 }
505
+        //             } else {
506
+        //                 currentElement = targetElement;
507
+        //                 continue;
508
+        //             }
509
+
510
+        //             if (!target || target === targetElement ||
511
+        //                 (target && FocusManager.GetCanSkipPreviousFocus(target))) {
512
+        //                 if (target === targetElement && target instanceof ButtonBase) {
513
+        //                     return !this.ButtonClickTick(target);
514
+        //                 }
515
+        //                 return true;
516
+        //             } else {
517
+        //                 currentElement = targetElement;
518
+        //                 continue;
519
+        //             }
520
+        //         }
521
+        //     }
522
+
523
+        // return false;
524
+        //     }
525
+
526
+        //     private IsEnableFocus(ele: FrameworkElement): boolean {
527
+        //     return null;//ele.IsEnabled && ele.IsVisible && (ele.Focusable || getAttachedProperty(ele, "IsInternalKeyboardControlling"));
528
+        // }
529
+
530
+        //     public MoveFocusElement(target: FrameworkElement): boolean {
531
+        //     if (this._focusList && this._currentFocusedElement) {
532
+        //         // const currentIndex = this._focusList.IndexOf(this._currentFocusedElement);
533
+        //         // let targetIndex = this._focusList.IndexOf(target);
534
+
535
+        //         // if (targetIndex < 0) {
536
+        //         //     while (true) {
537
+        //         //         target = LogicalTreeHelper.GetParent(target) as FrameworkElement;
538
+        //         //         if (!target || target instanceof IPage) {
539
+        //         //             return false;
540
+        //         //         }
541
+        //         //         targetIndex = this._focusList.IndexOf(target);
542
+        //         //         if (targetIndex >= 0) break;
543
+        //         //     }
544
+        //         // }
545
+
546
+        //         // if (currentIndex === targetIndex) return true;
547
+
548
+        //         // const result = this.MoveFocusHost(targetIndex > currentIndex ? FocusNavigation.Forward : FocusNavigation.Backward, target);
549
+        //         return result === true;
550
+        //     }
551
+        return false;
552
+    }
553
+}
554
+
555
+// 模拟其他类和工具函数
556
+class TextBox extends FrameworkElement {
557
+    Text = "";
558
+}
559
+
560
+class ButtonBase extends FrameworkElement { }
561
+
562
+class LogicalTreeHelper {
563
+    static GetParent(element: FrameworkElement): FrameworkElement | null {
564
+        return null;
565
+    }
566
+}
567
+
568
+class HotKeyHelper {
569
+    static GetKeyName(key: string): string {
570
+        return key;
571
+    }
572
+}
573
+
574
+// 其他模拟类和工具函数可按需添加
575
+//TODO 焦点控制 后续处理

+ 187
- 0
ant-design-pro-vue3/src/views/front/platfrom/presentation/FocusManagers/FocusManagerExt.ts View File

@@ -0,0 +1,187 @@
1
+// // 假设 FieldPolicyCollection 和 TipAdorner 等类型的定义
2
+// interface FieldPolicy {
3
+//     Run(d: any, message: string): void;
4
+// }
5
+
6
+// interface FieldPolicyCollection {
7
+//     [index: number]: FieldPolicy;
8
+// }
9
+
10
+// // 定义焦点管理器实例接口
11
+// interface FocusManagerInstance {
12
+//     IsFocusContinue: boolean;
13
+// }
14
+
15
+// // 焦点管理器类
16
+// class FocusManager {
17
+//     // 模拟获取焦点管理器实例
18
+//     static GetManagerInstance(d: any): FocusManagerInstance | null {
19
+//         return { IsFocusContinue: true };
20
+//     }
21
+
22
+//     // 模拟添加焦点丢失事件处理程序
23
+//     static AddPreviewLostFocusHandler(d: any, handler: (sender: any, args: any) => void) {
24
+//         if (d.addEventListener) {
25
+//             d.addEventListener('blur', handler);
26
+//         }
27
+//     }
28
+
29
+//     // 模拟移除焦点丢失事件处理程序
30
+//     static RemovePreviewLostFocusHandler(d: any, handler: (sender: any, args: any) => void) {
31
+//         if (d.removeEventListener) {
32
+//             d.removeEventListener('blur', handler);
33
+//         }
34
+//     }
35
+// }
36
+
37
+// // 焦点管理器扩展类
38
+// class FocusManagerExt {
39
+//     // 定义静态属性
40
+//     static AssertNotEmptyProperty = Symbol('AssertNotEmpty');
41
+//     static RegexValidationProperty = Symbol('RegexValidation');
42
+//     static RegexValidateErrorInfoProperty = Symbol('RegexValidateErrorInfo');
43
+//     static ValidationFieldProperty = Symbol('ValidationField');
44
+//     static FieldEmptyPoliciesProperty = Symbol('FieldEmptyPolicies');
45
+//     static RegexValidateErrorPoliciesProperty = Symbol('RegexValidateErrorPolicies');
46
+//     static IsFocusAdornerProperty = Symbol('IsFocusAdorner');
47
+
48
+//     // Getter 和 Setter 方法
49
+//     static GetAssertNotEmpty(d: any): boolean {
50
+//         return d[this.AssertNotEmptyProperty] || false;
51
+//     }
52
+
53
+//     static SetAssertNotEmpty(d: any, value: boolean) {
54
+//         d[this.AssertNotEmptyProperty] = value;
55
+//         this.OnAssertNotEmptyChanged(d, value);
56
+//     }
57
+
58
+//     static GetRegexValidation(d: any): string {
59
+//         return d[this.RegexValidationProperty] || '';
60
+//     }
61
+
62
+//     static SetRegexValidation(d: any, value: string) {
63
+//         d[this.RegexValidationProperty] = value;
64
+//         this.OnRegexValidationChanged(d, value);
65
+//     }
66
+
67
+//     static GetRegexValidateErrorInfo(d: any): string {
68
+//         return d[this.RegexValidateErrorInfoProperty] || '';
69
+//     }
70
+
71
+//     static SetRegexValidateErrorInfo(d: any, value: string) {
72
+//         d[this.RegexValidateErrorInfoProperty] = value;
73
+//     }
74
+
75
+//     static GetValidationField(d: any): string {
76
+//         return d[this.ValidationFieldProperty] || '';
77
+//     }
78
+
79
+//     static SetValidationField(d: any, value: string) {
80
+//         d[this.ValidationFieldProperty] = value;
81
+//     }
82
+
83
+//     static GetFieldEmptyPolicies(d: any): FieldPolicyCollection | null {
84
+//         return d[this.FieldEmptyPoliciesProperty] || null;
85
+//     }
86
+
87
+//     static SetFieldEmptyPolicies(d: any, value: FieldPolicyCollection) {
88
+//         d[this.FieldEmptyPoliciesProperty] = value;
89
+//     }
90
+
91
+//     static GetRegexValidateErrorPolicies(d: any): FieldPolicyCollection | null {
92
+//         return d[this.RegexValidateErrorPoliciesProperty] || null;
93
+//     }
94
+
95
+//     static SetRegexValidateErrorPolicies(d: any, value: FieldPolicyCollection) {
96
+//         d[this.RegexValidateErrorPoliciesProperty] = value;
97
+//     }
98
+
99
+//     static GetIsFocusAdorner(d: any): boolean {
100
+//         return d[this.IsFocusAdornerProperty] || false;
101
+//     }
102
+
103
+//     static SetIsFocusAdorner(d: any, value: boolean) {
104
+//         d[this.IsFocusAdornerProperty] = value;
105
+//     }
106
+
107
+//     // 属性变化处理方法
108
+//     private static OnAssertNotEmptyChanged(d: any, newValue: boolean) {
109
+//         if (newValue) {
110
+//             FocusManager.AddPreviewLostFocusHandler(d, this.handler);
111
+//         } else {
112
+//             FocusManager.RemovePreviewLostFocusHandler(d, this.handler);
113
+//         }
114
+//     }
115
+
116
+//     private static handler = (sender: any, args: any) => {
117
+//         const d = sender;
118
+//         const focus = FocusManager.GetManagerInstance(d);
119
+//         if (!focus) return;
120
+
121
+//         const propertyName = this.GetValidationField(d);
122
+//         if (!propertyName) return;
123
+
124
+//         const propertyInfo = d[propertyName];
125
+//         if (propertyInfo) {
126
+//             const strValue = String(propertyInfo);
127
+//             if (strValue.trim() !== '') return;
128
+//         }
129
+
130
+//         const fieldEmptyPolicies = this.GetFieldEmptyPolicies(d);
131
+//         if (fieldEmptyPolicies) {
132
+//             for (const policy of fieldEmptyPolicies) {
133
+//                 policy.Run(d, '该输入要素不能为空');
134
+//             }
135
+//         }
136
+
137
+//         focus.IsFocusContinue = false;
138
+//         args.preventDefault();
139
+//     };
140
+
141
+//     private static OnRegexValidationChanged(dp: any, newRegexValidation: string) {
142
+//         const handler = (sender: any, args: any) => {
143
+//             const d = sender;
144
+//             const focus = FocusManager.GetManagerInstance(d);
145
+//             if (!focus) return;
146
+
147
+//             const propertyName = this.GetValidationField(d);
148
+//             if (!propertyName) return;
149
+
150
+//             const propertyInfo = d[propertyName];
151
+//             if (!propertyInfo) return;
152
+
153
+//             const strValue = String(propertyInfo);
154
+//             if (!this.GetAssertNotEmpty(d) && strValue === '') return;
155
+
156
+//             const reg = this.GetRegexValidation(d);
157
+//             if (!reg) return;
158
+
159
+//             const regex = new RegExp(reg);
160
+//             if (regex.test(strValue)) return;
161
+
162
+//             const fieldPolicies = this.GetFieldEmptyPolicies(d);
163
+//             let regexValidateErrorInfo = this.GetRegexValidateErrorInfo(d);
164
+//             if (!regexValidateErrorInfo) {
165
+//                 regexValidateErrorInfo = `输入场要求输入值满足正则表达式:${reg},输入值:${strValue}不满足此要求!`;
166
+//             }
167
+
168
+//             if (fieldPolicies) {
169
+//                 for (const policy of fieldPolicies) {
170
+//                     policy.Run(d, regexValidateErrorInfo);
171
+//                 }
172
+//             }
173
+
174
+//             focus.IsFocusContinue = false;
175
+//             args.preventDefault();
176
+//         };
177
+
178
+//         if (newRegexValidation) {
179
+//             FocusManager.AddPreviewLostFocusHandler(dp, handler);
180
+//         } else {
181
+//             FocusManager.RemovePreviewLostFocusHandler(dp, handler);
182
+//         }
183
+//     }
184
+// }
185
+
186
+// export default FocusManagerExt;
187
+//焦点控制TODO后续处理

+ 42
- 0
ant-design-pro-vue3/src/views/front/platfrom/presentation/Interfaces/Ipage.ts View File

@@ -0,0 +1,42 @@
1
+// 定义 Disposable 接口,模拟 C# 的 IDisposable
2
+interface Disposable {
3
+    dispose(): void;
4
+}
5
+
6
+// 假设 PageContainer 类型定义
7
+class PageContainer {}
8
+
9
+// 定义 IPage 接口
10
+export interface IPage extends Disposable {
11
+    /**
12
+     * 实例化ID
13
+     */
14
+    readonly InstanceId: string;
15
+    /**
16
+     * 设置ID
17
+     * @param guid 要设置的实例化 ID
18
+     */
19
+    SetInstanceId(guid: string): void;
20
+    /**
21
+     * 视图状态数据集合
22
+     */
23
+    readonly ViewStateData: { [key: string]: any };
24
+    /**
25
+     * 设置视图状态数据集合
26
+     * @param viewStateData 要设置的视图状态数据集合
27
+     */
28
+    SetViewStateData(viewStateData: { [key: string]: any }): void;
29
+    /**
30
+     * 交易父容器
31
+     */
32
+    readonly OwnerContainer: PageContainer;
33
+    /**
34
+     * 设置交易父容器
35
+     * @param pageContainer 要设置的交易父容器
36
+     */
37
+    SetOwnerContainer(pageContainer: PageContainer): void;
38
+    /**
39
+     * 释放资源
40
+     */
41
+    dispose(): void;
42
+}

+ 21
- 0
ant-design-pro-vue3/src/views/front/platfrom/presentation/PageFunctions/PageClosedEventArgs.ts View File

@@ -0,0 +1,21 @@
1
+// 定义一个模拟的 Guid 类型,在 TypeScript 中没有内置的 Guid,用字符串模拟
2
+type Guid = string;
3
+
4
+// 定义 EventArgs 基类
5
+class EventArgs {
6
+    constructor() {}
7
+}
8
+
9
+// 定义 PageClosedEventArgs 类
10
+export class PageClosedEventArgs extends EventArgs {
11
+    // 页面实例 ID
12
+    public readonly InstanceId: Guid;
13
+    // 页面关闭时要导出的参数
14
+    public readonly ExportArgs: { [key: string]: any };
15
+
16
+    constructor(instanceId: Guid, exportArgs: { [key: string]: any }) {
17
+        super();
18
+        this.InstanceId = instanceId;
19
+        this.ExportArgs = exportArgs;
20
+    }
21
+}

+ 265
- 0
ant-design-pro-vue3/src/views/front/platfrom/presentation/PageFunctions/PageContainer.ts View File

@@ -0,0 +1,265 @@
1
+import { ConfigManager } from "../../common/RunningParameters/ConfigManager";
2
+// import FocusManager from "../FocusManagers/FocusManager";
3
+import PlatformLogger from "../../common/RunningParameters/PlatformSettings";
4
+// 定义 IPage 接口
5
+interface IPage {
6
+    InstanceId: string;
7
+    SetOwnerContainer(container: PageContainer): void;
8
+    SetInstanceId(id: string): void;
9
+    ViewStateData: { [key: string]: any };
10
+}
11
+
12
+// 定义 PageClosedEventArgs 接口
13
+interface PageClosedEventArgs {
14
+    InstanceId: string;
15
+    ViewStateData: { [key: string]: any };
16
+}
17
+
18
+// 定义 FocusManager 接口
19
+enum ConfigType {
20
+    System,
21
+    Client,
22
+    User
23
+}
24
+
25
+// 定义 PageContainer 类
26
+class PageContainer {
27
+    private _pageStack: IPage[] = [];
28
+    public AllPagesClosed: ((sender: PageContainer, args: PageClosedEventArgs) => void) | null = null;
29
+    private _currentPage: IPage | null = null;
30
+    public get CurrentPage(): IPage | null {
31
+        return this._currentPage;
32
+    }
33
+    private set CurrentPage(value: IPage | null) {
34
+        this._currentPage = value;
35
+        this.RaisePropertyChanged("CurrentPage");
36
+    }
37
+
38
+    private _ClosedCallbackList: { [key: string]: (page: IPage) => void } = {};
39
+
40
+    public IsShowInfo: boolean = false;
41
+    public DisplayInfoList: any[] = [];
42
+    public BusyStateTip: string = "数据处理中...";
43
+    public IsBusy: boolean = false;
44
+    public IsOverlay: boolean = false;
45
+
46
+    private _busyAdorner: HTMLElement | null = null;
47
+    private _sprocket: HTMLElement | null = null;
48
+
49
+    constructor() {
50
+        // 模拟 WPF 的静态构造函数逻辑
51
+        // 在 TypeScript 中无法直接实现静态构造函数,这里可以在实例构造函数中初始化一些静态相关的逻辑
52
+    }
53
+
54
+    public OnContentChanged(oldContent: any, newContent: any): void {
55
+        const page = newContent as IPage;
56
+        if (page === null && newContent !== null) {
57
+            throw new Error("Content必须继承IPage对象");
58
+        }
59
+
60
+        if (page !== null && page.InstanceId !== "") {
61
+            this.CurrentPage = page;
62
+
63
+            if (!this._pageStack.includes(page)) {
64
+                page.SetOwnerContainer(this);
65
+                this._pageStack.push(page);
66
+            }
67
+        }
68
+    }
69
+
70
+    public PushPage(page: IPage, closedCallback: ((page: IPage) => void) | null = null): string {
71
+        if (page === null) {
72
+            return "";
73
+        } else {
74
+            if (page.InstanceId === "") {
75
+                page.SetInstanceId(this.generateGuid());
76
+            }
77
+            if (closedCallback !== null) {
78
+                this._ClosedCallbackList[page.InstanceId] = closedCallback;
79
+            }
80
+            // 模拟移除父元素的逻辑
81
+            // 在 Web 环境中,可能需要根据具体情况实现
82
+            this.OnContentChanged(null, page);
83
+            return page.InstanceId;
84
+        }
85
+    }
86
+
87
+    public ClosePage(): { [key: string]: any } | null {
88
+        if (this._currentPage !== null) {
89
+            const closePage = this._currentPage;
90
+            this._pageStack.pop();
91
+
92
+            if (this._pageStack.length > 0) {
93
+                this.OnContentChanged(null, this._pageStack[this._pageStack.length - 1]);
94
+            } else {
95
+                if (this.AllPagesClosed !== null) {
96
+                    this.AllPagesClosed(this, {
97
+                        InstanceId: closePage.InstanceId,
98
+                        ViewStateData: closePage.ViewStateData
99
+                    });
100
+                }
101
+            }
102
+            if (this._ClosedCallbackList[closePage.InstanceId]) {
103
+                this._ClosedCallbackList[closePage.InstanceId](closePage);
104
+            }
105
+            closePage.SetInstanceId("");
106
+            return closePage.ViewStateData;
107
+        }
108
+
109
+        return null;
110
+    }
111
+
112
+    public CloseAndOpenPage(page: IPage): string {
113
+        if (page === null) {
114
+            return "";
115
+        } else {
116
+            if (this._currentPage !== null) {
117
+                this._currentPage.SetInstanceId("");
118
+                this._pageStack.pop();
119
+            }
120
+
121
+            return this.PushPage(page);
122
+        }
123
+    }
124
+
125
+    public OnApplyTemplate(): void {
126
+        this._busyAdorner = document.getElementById("BusyAdorner");
127
+        this._sprocket = document.getElementById("sprocketControl");
128
+    }
129
+
130
+    public SetBusyAdorner(isBusy: boolean, tip: string | null): void {
131
+        if (this._busyAdorner !== null) {
132
+            this._busyAdorner.textContent = tip ?? "正在处理...";
133
+            this._busyAdorner.style.display = isBusy ? "block" : "none";
134
+            if (this._sprocket !== null) {
135
+                // 模拟 IsIndeterminate 属性
136
+                // 在 Web 环境中,可能需要根据具体情况实现
137
+            }
138
+        }
139
+    }
140
+
141
+    public set IsBusyValue(value: boolean) {
142
+        this.IsBusy = value;
143
+        this.OnIsBusyChanged();
144
+    }
145
+
146
+    private OnIsBusyChanged(): void {
147
+        //TODO焦点控制需要用到微软的框架
148
+        const focusManager = null;//FocusManager.GetManagerInstance(this);
149
+        if (focusManager !== null) {
150
+            focusManager.CanAcceptUserInput = !this.IsBusy;
151
+        } else {
152
+            const handler = (e: KeyboardEvent) => {
153
+                e.preventDefault();
154
+            };
155
+            if (this.IsBusy) {
156
+                document.addEventListener("keydown", handler);
157
+            } else {
158
+                document.removeEventListener("keydown", handler);
159
+            }
160
+
161
+            const mouseHandler = (e: MouseEvent) => {
162
+                e.preventDefault();
163
+            };
164
+            if (this.IsBusy) {
165
+                document.addEventListener("mousedown", mouseHandler);
166
+                document.addEventListener("mouseup", mouseHandler);
167
+            } else {
168
+                document.removeEventListener("mousedown", mouseHandler);
169
+                document.removeEventListener("mouseup", mouseHandler);
170
+            }
171
+        }
172
+        this.SetBusyAdorner(this.IsBusy, this.BusyStateTip);
173
+    }
174
+
175
+    public async ModalInvoke(action: () => Promise<void>, busyStateTip: string): Promise<void> {
176
+        this.BusyStateTip = busyStateTip;
177
+        this.IsBusyValue = true;
178
+
179
+        if (ConfigManager.GetInstance().GetConfigValue("ModalInvoke", ConfigType.Client) !== "Legacy") {
180
+            try {
181
+                const win = new ModalWindow(action);
182
+                win.DelayCancel = 120;
183
+                await win.showDialog();
184
+                this.IsBusyValue = false;
185
+                if (win.IsCancel) {
186
+                    throw new Error("用户强制中断了操作!");
187
+                }
188
+                return;
189
+            } catch (ex) {
190
+                PlatformLogger.SystemErrorInfo("ModalInvoke:初始化ModalWindow发生异常!", ex as Error);
191
+            }
192
+        }
193
+
194
+        try {
195
+            await action();
196
+        } finally {
197
+            this.IsBusyValue = false;
198
+        }
199
+    }
200
+
201
+    private RaisePropertyChanged(propertyName: string): void {
202
+        // 模拟属性变更通知
203
+        // 在 Vue 中,可以使用事件或响应式系统实现
204
+    }
205
+
206
+    private generateGuid(): string {
207
+        return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
208
+            const r = Math.random() * 16 | 0,
209
+                v = c === 'x' ? r : (r & 0x3 | 0x8);
210
+            return v.toString(16);
211
+        });
212
+    }
213
+}
214
+
215
+// 定义 ModalWindow 类
216
+class ModalWindow {
217
+    private action: () => Promise<void>;
218
+    private thread: NodeJS.Timeout | null = null;
219
+    private watch: number = Date.now();
220
+    public DelayCancel: number = 30;
221
+    public IsCancel: boolean = false;
222
+
223
+    constructor(action: () => Promise<void>) {
224
+        this.action = action;
225
+    }
226
+
227
+    public async showDialog(): Promise<void> {
228
+        const dialog = document.createElement("div");
229
+        dialog.style.position = "fixed";
230
+        dialog.style.bottom = "0";
231
+        dialog.style.left = "0";
232
+        dialog.style.backgroundColor = "rgba(0, 0, 0, 0.5)";
233
+        dialog.style.color = "white";
234
+        dialog.style.padding = "10px";
235
+        dialog.textContent = "系统处理中...";
236
+        document.body.appendChild(dialog);
237
+
238
+        try {
239
+            this.thread = setTimeout(() => {
240
+                this.action().then(() => {
241
+                    dialog.remove();
242
+                }).catch((ex) => {
243
+                    PlatformLogger.SystemErrorInfo("ModalInvoke2Dialog:调用发生异常!", ex);
244
+                    dialog.remove();
245
+                });
246
+            }, 0);
247
+
248
+            document.addEventListener("keydown", this.handleKeyDown.bind(this));
249
+        } finally {
250
+            document.removeEventListener("keydown", this.handleKeyDown.bind(this));
251
+        }
252
+    }
253
+
254
+    private handleKeyDown(e: KeyboardEvent): void {
255
+        if ((Date.now() - this.watch) / 1000 < this.DelayCancel) return;
256
+        if (e.key === "x" && e.ctrlKey) {
257
+            if (this.thread !== null) {
258
+                clearTimeout(this.thread);
259
+                this.IsCancel = true;
260
+            }
261
+        }
262
+    }
263
+}
264
+
265
+export { PageContainer };

+ 84
- 0
ant-design-pro-vue3/src/views/front/platfrom/presentation/PageFunctions/PageExtension.ts View File

@@ -0,0 +1,84 @@
1
+// 定义 IPage 接口
2
+interface IPage {
3
+    OwnerContainer: PageContainer | null;
4
+}
5
+
6
+// 定义 PageContainer 接口
7
+interface PageContainer {
8
+    ClosePage(): void;
9
+    PushPage(actionName: string, importArgs?: Record<string, any>): string;
10
+    PushPage(page: IPage): string;
11
+}
12
+
13
+// 定义 PageExtension 类
14
+export class PageExtension {
15
+    /**
16
+     * 关闭并打开新的交易 - 扩展方法
17
+     * @param target 当前的交易
18
+     * @param actionName 交易的全名(例如:PlatformManage.T7801)
19
+     * @param importArgs 维护视图数据
20
+     */
21
+    static CloseAndOpenTradePage(target: IPage, actionName: string, importArgs?: Record<string, any>): string {
22
+        const tradePageContainer = target.OwnerContainer;
23
+        if (!tradePageContainer) {
24
+            return '00000000-0000-0000-0000-000000000000';
25
+        }
26
+        tradePageContainer.ClosePage();
27
+        return tradePageContainer.PushPage(actionName, importArgs);
28
+    }
29
+
30
+    /**
31
+     * 关闭并打开新的交易 - 扩展方法
32
+     * @param target 当前的交易
33
+     * @param page 要打开的页面
34
+     */
35
+    static CloseAndOpenTradePageWithPage(target: IPage, page: IPage): string {
36
+        const tradePageContainer = target.OwnerContainer;
37
+        if (!tradePageContainer) {
38
+            return '00000000-0000-0000-0000-000000000000';
39
+        }
40
+        tradePageContainer.ClosePage();
41
+        return tradePageContainer.PushPage(page);
42
+    }
43
+
44
+    /**
45
+     * 打开交易 - 扩展方法
46
+     * @param target 当前交易
47
+     * @param actionName 交易的全名(例如:PlatformManage.T7801)
48
+     * @param importArgs 维护视图数据
49
+     */
50
+    static OpenPage(target: IPage, actionName: string, importArgs?: Record<string, any>): string {
51
+        const tradePageContainer = target.OwnerContainer;
52
+        if (!tradePageContainer) {
53
+            return '00000000-0000-0000-0000-000000000000';
54
+        }
55
+        return tradePageContainer.PushPage(actionName, importArgs);
56
+    }
57
+
58
+    /**
59
+     * 打开交易 - 扩展方法
60
+     * @param target 当前交易
61
+     * @param page 要打开的页面
62
+     */
63
+    static OpenPageWithPage(target: IPage, page: IPage): string {
64
+        if (!page) {
65
+            throw new Error('page is not null');
66
+        }
67
+        const tradePageContainer = target.OwnerContainer;
68
+        if (!tradePageContainer) {
69
+            return '00000000-0000-0000-0000-000000000000';
70
+        }
71
+        return tradePageContainer.PushPage(page);
72
+    }
73
+
74
+    /**
75
+     * 关闭页面
76
+     * @param target 当前页面
77
+     */
78
+    static Close(target: IPage): void {
79
+        const tradePageContainer = target.OwnerContainer;
80
+        if (tradePageContainer) {
81
+            tradePageContainer.ClosePage();
82
+        }
83
+    }
84
+}

+ 175
- 0
ant-design-pro-vue3/src/views/front/platfrom/presentation/PageFunctions/PageFactory.ts View File

@@ -0,0 +1,175 @@
1
+import * as fs from 'fs';
2
+import * as path from 'path';
3
+import * as crypto from 'crypto';
4
+
5
+// 假设 IPage 接口定义如下
6
+interface IPage {
7
+    SetInstanceId(id: string): void;
8
+}
9
+
10
+// 假设 PageContainer 类定义如下
11
+class PageContainer {
12
+    ModalInvoke(action: () => void, message: string) {
13
+        action();
14
+    }
15
+}
16
+
17
+// 假设 PlatformSettings 类定义如下
18
+class PlatformSettings {
19
+    static IsDebugMode = false;
20
+    static PagesDirectory = 'pages';
21
+}
22
+
23
+// 假设 ConfigManager 类定义如下
24
+class ConfigManager {
25
+    private static instance: ConfigManager;
26
+
27
+    static GetInstance() {
28
+        if (!this.instance) {
29
+            this.instance = new ConfigManager();
30
+        }
31
+        return this.instance;
32
+    }
33
+
34
+    GetConfigValue(key: string, configType: any) {
35
+        return 'false';
36
+    }
37
+}
38
+
39
+// 假设 ConfigType 枚举定义如下
40
+enum ConfigType {
41
+    System
42
+}
43
+
44
+// 假设 FilesHandle 类定义如下
45
+class FilesHandle {
46
+    static UpdateAssemblys: { [key: string]: boolean } = {};
47
+
48
+    static UpdateTradeDll(actionName: string) {
49
+        return true;
50
+    }
51
+}
52
+
53
+// 假设 FileHandle 类定义如下
54
+class FileHandle {
55
+    static GetFileMD5(fileInfo: { path: string }) {
56
+        const data = fs.readFileSync(fileInfo.path);
57
+        return crypto.createHash('md5').update(data).digest('hex');
58
+    }
59
+}
60
+
61
+// 假设 PlatformLogger 类定义如下
62
+class PlatformLogger {
63
+    static SystemInfo(message: string) {
64
+        console.log(message);
65
+    }
66
+}
67
+
68
+class PageFactory {
69
+    private static Logger = {
70
+        Error(message: string) {
71
+            console.error(message);
72
+        }
73
+    };
74
+
75
+    private static LoadedActionTypes: { [key: string]: any } = {};
76
+    private static LoadedActionMD5: { [key: string]: string } = {};
77
+
78
+    static CreatePage(actionName: string, pageContainer?: PageContainer): IPage | null {
79
+        let actionType: any = null;
80
+        if (!pageContainer) {
81
+            actionType = this.GetActionType(actionName);
82
+        } else {
83
+            pageContainer.ModalInvoke(() => {
84
+                actionType = this.GetActionType(actionName);
85
+            }, "正在加载交易页面,请稍后...");
86
+        }
87
+        if (!actionType) {
88
+            this.Logger.Error(`加载文件名为:【${actionName}】的交易失败!`);
89
+            return null;
90
+        } else {
91
+            const page = new actionType() as IPage;
92
+            if (page) {
93
+                page.SetInstanceId(this.generateGuid());
94
+            }
95
+            return page;
96
+        }
97
+    }
98
+
99
+    private static GetActionType(actionName: string): any {
100
+        let actionType: any = null;
101
+
102
+        if (!PlatformSettings.IsDebugMode) {
103
+            let flag = false;
104
+            flag = Boolean(ConfigManager.GetInstance().GetConfigValue("IsFromProjectDownLoadTradeDll", ConfigType.System));
105
+            if (!flag) {
106
+                PlatformLogger.SystemInfo(`Update Trade File,FileName:[${actionName}]`);
107
+                if (!FilesHandle.UpdateTradeDll(actionName)) {
108
+                    return null;
109
+                }
110
+            } else {
111
+                PlatformLogger.SystemInfo(`已由项目层检测和下载交易的dll:[${actionName}]`);
112
+            }
113
+        }
114
+
115
+        if (PlatformSettings.IsDebugMode || !this.LoadedActionTypes[actionName]
116
+            || (FilesHandle.UpdateAssemblys[actionName] && FilesHandle.UpdateAssemblys[actionName])) {
117
+            const fileName = `${actionName}.dll`;
118
+            const pagesDirectory = PlatformSettings.PagesDirectory;
119
+            const filePath = path.join(process.cwd(), pagesDirectory, fileName);
120
+            if (fs.existsSync(filePath)) {
121
+                const fileMD5 = FileHandle.GetFileMD5({ path: filePath });
122
+                if (PlatformSettings.IsDebugMode && this.LoadedActionMD5[actionName] && this.LoadedActionMD5[actionName] === fileMD5
123
+                    && this.LoadedActionTypes[actionName]) {
124
+                    return this.LoadedActionTypes[actionName];
125
+                } else {
126
+                    this.LoadedActionMD5[actionName] = fileMD5;
127
+                }
128
+
129
+                const rawAssembly = this.loadFile(filePath);
130
+                // 这里无法直接加载 DLL,仅作示例
131
+                // 假设存在一个模块加载函数
132
+                const assembly = this.loadModule(rawAssembly);
133
+                if (!assembly) return null;
134
+                for (const key in assembly) {
135
+                    if (assembly.hasOwnProperty(key)) {
136
+                        const type = assembly[key];
137
+                        if (this.isIPage(type)) {
138
+                            this.LoadedActionTypes[type.name] = type;
139
+                        }
140
+                    }
141
+                }
142
+                actionType = this.LoadedActionTypes[actionName];
143
+            }
144
+        }
145
+
146
+        return actionType;
147
+    }
148
+
149
+    private static loadFile(filename: string): Buffer {
150
+        if (!fs.existsSync(filename)) {
151
+            return Buffer.alloc(0);
152
+        }
153
+        return fs.readFileSync(filename);
154
+    }
155
+
156
+    private static generateGuid() {
157
+        return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
158
+            const r = Math.random() * 16 | 0;
159
+            const v = c === 'x' ? r : (r & 0x3 | 0x8);
160
+            return v.toString(16);
161
+        });
162
+    }
163
+
164
+    private static isIPage(type: any): boolean {
165
+        // 简单判断是否实现了 IPage 接口
166
+        return typeof type.prototype.SetInstanceId === 'function';
167
+    }
168
+
169
+    private static loadModule(rawAssembly: Buffer): any {
170
+        // 这里无法直接加载 DLL,仅作示例
171
+        return {};
172
+    }
173
+}
174
+
175
+export { PageFactory };

+ 384
- 0
ant-design-pro-vue3/src/views/front/platfrom/presentation/PageFunctions/SprocketControl.ts View File

@@ -0,0 +1,384 @@
1
+// 定义旋转方向枚举
2
+export enum Direction {
3
+  CLOCKWISE,
4
+  ANTICLOCKWISE
5
+}
6
+
7
+// 定义辐条结构体
8
+interface Spoke {
9
+  StartPoint: { x: number; y: number };
10
+  EndPoint: { x: number; y: number };
11
+}
12
+
13
+export class SprocketControl {
14
+  // 常量
15
+  private static readonly DEFAULT_INTERVAL = 60;
16
+  private static readonly DEFAULT_TICK_COLOR = { r: 58, g: 58, b: 58, a: 255 };
17
+  private static readonly DEFAULT_TICK_WIDTH = 3;
18
+  private static readonly DEFAULT_TICK_COUNT = 12;
19
+  private static readonly MINIMUM_INNER_RADIUS = 5;
20
+  private static readonly MINIMUM_OUTER_RADIUS = 8;
21
+  private static readonly MINIMUM_CONTROL_SIZE = { width: 28, height: 28 };
22
+  private static readonly MINIMUM_PEN_WIDTH = 2;
23
+  private static readonly DEFAULT_START_ANGLE = 270;
24
+  private static readonly INNER_RADIUS_FACTOR = 0.175;
25
+  private static readonly OUTER_RADIUS_FACTOR = 0.3125;
26
+  private static readonly ALPHA_UPPER_LIMIT = 250;
27
+  private static readonly ALPHA_LOWER_LIMIT = 0;
28
+  private static readonly ALPHA_TICK_PERCENTAGE_LOWER_LIMIT = 10;
29
+  private static readonly DEFAULT_PROGRESS_ALPHA = 10;
30
+  private static readonly DEFAULT_PROGRESS = 0.0;
31
+
32
+  // 字段
33
+  private centerPoint = { x: 0, y: 0 };
34
+  private innerRadius = 0;
35
+  private outerRadius = 0;
36
+  private alphaChange = 0;
37
+  private angleIncrement = 0;
38
+  private renderStartAngle = 0;
39
+  private renderTimer: number | null = null;
40
+  private spokes: Spoke[] = [];
41
+
42
+  // 依赖属性
43
+  private _interval = SprocketControl.DEFAULT_INTERVAL;
44
+  private _isIndeterminate = true;
45
+  private _progress = SprocketControl.DEFAULT_PROGRESS;
46
+  private _rotation = Direction.CLOCKWISE;
47
+  private _startAngle = SprocketControl.DEFAULT_START_ANGLE;
48
+  private _tickColor = SprocketControl.DEFAULT_TICK_COLOR;
49
+  private _tickCount = SprocketControl.DEFAULT_TICK_COUNT;
50
+  private _tickStyle: CanvasLineCap = 'round';
51
+  private _tickWidth = SprocketControl.DEFAULT_TICK_WIDTH;
52
+  private _lowestAlpha = SprocketControl.ALPHA_LOWER_LIMIT;
53
+  private _alphaTicksPercentage = 100.0;
54
+
55
+  // 构造函数
56
+  constructor(private canvas: HTMLCanvasElement) {
57
+    this.calculateSpokesPoints();
58
+    this.canvas.addEventListener('resize', () => this.onRenderSizeChanged());
59
+  }
60
+
61
+  // 属性访问器
62
+  get Interval() {
63
+    return this._interval;
64
+  }
65
+  set Interval(value: number) {
66
+    const oldValue = this._interval;
67
+    this._interval = value;
68
+    this.onIntervalChanged(oldValue, value);
69
+  }
70
+
71
+  get IsIndeterminate() {
72
+    return this._isIndeterminate;
73
+  }
74
+  set IsIndeterminate(value: boolean) {
75
+    const oldValue = this._isIndeterminate;
76
+    this._isIndeterminate = value;
77
+    this.onIsIndeterminateChanged(oldValue, value);
78
+  }
79
+
80
+  get Progress() {
81
+    return this._progress;
82
+  }
83
+  set Progress(value: number) {
84
+    const coercedValue = this.coerceProgress(value);
85
+    const oldValue = this._progress;
86
+    this._progress = coercedValue;
87
+    this.onProgressChanged(oldValue, coercedValue);
88
+  }
89
+
90
+  get Rotation() {
91
+    return this._rotation;
92
+  }
93
+  set Rotation(value: Direction) {
94
+    const oldValue = this._rotation;
95
+    this._rotation = value;
96
+    this.onRotationChanged(oldValue, value);
97
+  }
98
+
99
+  get StartAngle() {
100
+    return this._startAngle;
101
+  }
102
+  set StartAngle(value: number) {
103
+    const oldValue = this._startAngle;
104
+    this._startAngle = value;
105
+    this.onStartAngleChanged(oldValue, value);
106
+  }
107
+
108
+  get TickColor() {
109
+    return this._tickColor;
110
+  }
111
+  set TickColor(value: { r: number; g: number; b: number; a: number }) {
112
+    const oldValue = this._tickColor;
113
+    this._tickColor = value;
114
+    this.onTickColorChanged(oldValue, value);
115
+  }
116
+
117
+  get TickCount() {
118
+    return this._tickCount;
119
+  }
120
+  set TickCount(value: number) {
121
+    const coercedValue = this.coerceTickCount(value);
122
+    const oldValue = this._tickCount;
123
+    this._tickCount = coercedValue;
124
+    this.onTickCountChanged(oldValue, coercedValue);
125
+  }
126
+
127
+  get TickStyle() {
128
+    return this._tickStyle;
129
+  }
130
+  set TickStyle(value: CanvasLineCap) {
131
+    const oldValue = this._tickStyle;
132
+    this._tickStyle = value;
133
+    this.onTickStyleChanged(oldValue, value);
134
+  }
135
+
136
+  get TickWidth() {
137
+    return this._tickWidth;
138
+  }
139
+  set TickWidth(value: number) {
140
+    const coercedValue = this.coerceTickWidth(value);
141
+    const oldValue = this._tickWidth;
142
+    this._tickWidth = coercedValue;
143
+    this.onTickWidthChanged(oldValue, coercedValue);
144
+  }
145
+
146
+  get LowestAlpha() {
147
+    return this._lowestAlpha;
148
+  }
149
+  set LowestAlpha(value: number) {
150
+    const coercedValue = this.coerceLowestAlpha(value);
151
+    const oldValue = this._lowestAlpha;
152
+    this._lowestAlpha = coercedValue;
153
+    this.onLowestAlphaChanged(oldValue, coercedValue);
154
+  }
155
+
156
+  get AlphaTicksPercentage() {
157
+    return this._alphaTicksPercentage;
158
+  }
159
+  set AlphaTicksPercentage(value: number) {
160
+    const coercedValue = this.coerceAlphaTicksPercentage(value);
161
+    const oldValue = this._alphaTicksPercentage;
162
+    this._alphaTicksPercentage = coercedValue;
163
+    this.onAlphaTicksPercentageChanged(oldValue, coercedValue);
164
+  }
165
+
166
+  // 辅助方法
167
+  private start() {
168
+    if (!this.renderTimer) {
169
+      this.renderTimer = window.setInterval(() => this.onRenderTimerElapsed(), this._interval);
170
+    }
171
+  }
172
+
173
+  private stop() {
174
+    if (this.renderTimer) {
175
+      window.clearInterval(this.renderTimer);
176
+      this.renderTimer = null;
177
+    }
178
+  }
179
+
180
+  private convertDegreesToRadians(degrees: number) {
181
+    return (Math.PI / 180) * degrees;
182
+  }
183
+
184
+  private calculateSpokesPoints() {
185
+    this.spokes = [];
186
+    this.angleIncrement = 360 / this._tickCount;
187
+    this.alphaChange = (255 - this._lowestAlpha) / ((this._alphaTicksPercentage / 100) * this._tickCount);
188
+    this.renderStartAngle = this._startAngle;
189
+
190
+    const width = Math.min(this.canvas.width, this.canvas.height);
191
+    this.centerPoint = { x: this.canvas.width / 2, y: this.canvas.height / 2 };
192
+    this.innerRadius = width * SprocketControl.INNER_RADIUS_FACTOR;
193
+    if (this.innerRadius < SprocketControl.MINIMUM_INNER_RADIUS) {
194
+      this.innerRadius = SprocketControl.MINIMUM_INNER_RADIUS;
195
+    }
196
+    this.outerRadius = width * SprocketControl.OUTER_RADIUS_FACTOR;
197
+    if (this.outerRadius < SprocketControl.MINIMUM_OUTER_RADIUS) {
198
+      this.outerRadius = SprocketControl.MINIMUM_OUTER_RADIUS;
199
+    }
200
+
201
+    let angle = 0;
202
+    for (let i = 0; i < this._tickCount; i++) {
203
+      const pt1 = {
204
+        x: this.innerRadius * Math.cos(this.convertDegreesToRadians(angle)),
205
+        y: this.innerRadius * Math.sin(this.convertDegreesToRadians(angle))
206
+      };
207
+      const pt2 = {
208
+        x: this.outerRadius * Math.cos(this.convertDegreesToRadians(angle)),
209
+        y: this.outerRadius * Math.sin(this.convertDegreesToRadians(angle))
210
+      };
211
+      this.spokes.push({ StartPoint: pt1, EndPoint: pt2 });
212
+
213
+      if (!this._isIndeterminate) {
214
+        angle += this.angleIncrement;
215
+      } else {
216
+        if (this._rotation === Direction.CLOCKWISE) {
217
+          angle -= this.angleIncrement;
218
+        } else {
219
+          angle += this.angleIncrement;
220
+        }
221
+      }
222
+    }
223
+  }
224
+
225
+  // 重写方法
226
+  private onRenderSizeChanged() {
227
+    this.calculateSpokesPoints();
228
+    this.render();
229
+  }
230
+
231
+  private render() {
232
+    const ctx = this.canvas.getContext('2d');
233
+    if (!ctx || !this.spokes) return;
234
+
235
+    ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
236
+    ctx.translate(this.centerPoint.x, this.centerPoint.y);
237
+    ctx.rotate(this.convertDegreesToRadians(this.renderStartAngle));
238
+
239
+    let alpha = 255;
240
+    const progressSpokes = Math.floor((this._progress * this._tickCount) / 100);
241
+
242
+    for (let i = 0; i < this._tickCount; i++) {
243
+      if (!this._isIndeterminate) {
244
+        if (progressSpokes > 0) {
245
+          alpha = i < progressSpokes ? 255 : SprocketControl.DEFAULT_PROGRESS_ALPHA;
246
+        } else {
247
+          alpha = SprocketControl.DEFAULT_PROGRESS_ALPHA;
248
+        }
249
+      }
250
+
251
+      ctx.strokeStyle = `rgba(${this._tickColor.r}, ${this._tickColor.g}, ${this._tickColor.b}, ${alpha / 255})`;
252
+      ctx.lineWidth = this._tickWidth;
253
+      ctx.lineCap = this._tickStyle;
254
+      ctx.beginPath();
255
+      ctx.moveTo(this.spokes[i].StartPoint.x, this.spokes[i].StartPoint.y);
256
+      ctx.lineTo(this.spokes[i].EndPoint.x, this.spokes[i].EndPoint.y);
257
+      ctx.stroke();
258
+
259
+      if (this._isIndeterminate) {
260
+        alpha -= this.alphaChange;
261
+        if (alpha < this._lowestAlpha) {
262
+          alpha = this._lowestAlpha;
263
+        }
264
+      }
265
+    }
266
+
267
+    ctx.setTransform(1, 0, 0, 1, 0, 0);
268
+  }
269
+
270
+  // 事件处理方法
271
+  private onRenderTimerElapsed() {
272
+    if (this._rotation === Direction.CLOCKWISE) {
273
+      this.renderStartAngle += this.angleIncrement;
274
+      if (this.renderStartAngle >= 360) {
275
+        this.renderStartAngle -= 360;
276
+      }
277
+    } else {
278
+      this.renderStartAngle -= this.angleIncrement;
279
+      if (this.renderStartAngle <= -360) {
280
+        this.renderStartAngle += 360;
281
+      }
282
+    }
283
+    this.render();
284
+  }
285
+
286
+  private onVisibilityChanged(isVisible: boolean) {
287
+    if (this._isIndeterminate) {
288
+      if (isVisible) {
289
+        this.start();
290
+      } else {
291
+        this.stop();
292
+      }
293
+    }
294
+  }
295
+
296
+  // 属性更改回调方法
297
+  private onIntervalChanged(oldValue: number, newValue: number) {
298
+    if (this.renderTimer) {
299
+      this.stop();
300
+      this.start();
301
+    }
302
+  }
303
+
304
+  private onIsIndeterminateChanged(oldValue: boolean, newValue: boolean) {
305
+    if (oldValue !== newValue) {
306
+      if (newValue) {
307
+        this.start();
308
+      } else {
309
+        this.stop();
310
+        this.render();
311
+      }
312
+    }
313
+  }
314
+
315
+  private onProgressChanged(oldValue: number, newValue: number) {
316
+    this.render();
317
+  }
318
+
319
+  private onRotationChanged(oldValue: Direction, newValue: Direction) {
320
+    this.calculateSpokesPoints();
321
+  }
322
+
323
+  private onStartAngleChanged(oldValue: number, newValue: number) {
324
+    this.calculateSpokesPoints();
325
+  }
326
+
327
+  private onTickColorChanged(oldValue: { r: number; g: number; b: number; a: number }, newValue: { r: number; g: number; b: number; a: number }) {
328
+    this.render();
329
+  }
330
+
331
+  private onTickCountChanged(oldValue: number, newValue: number) {
332
+    this.calculateSpokesPoints();
333
+  }
334
+
335
+  private onTickStyleChanged(oldValue: CanvasLineCap, newValue: CanvasLineCap) {
336
+    this.render();
337
+  }
338
+
339
+  private onTickWidthChanged(oldValue: number, newValue: number) {
340
+    this.render();
341
+  }
342
+
343
+  private onLowestAlphaChanged(oldValue: number, newValue: number) {
344
+    // 可根据需求添加逻辑
345
+  }
346
+
347
+  private onAlphaTicksPercentageChanged(oldValue: number, newValue: number) {
348
+    // 可根据需求添加逻辑
349
+  }
350
+
351
+  // 强制值回调方法
352
+  private coerceProgress(value: number) {
353
+    if (value < 0) return 0;
354
+    if (value > 100) return 100;
355
+    return value;
356
+  }
357
+
358
+  private coerceTickCount(value: number) {
359
+    if (value <= 0) return SprocketControl.DEFAULT_TICK_COUNT;
360
+    return value;
361
+  }
362
+
363
+  private coerceTickWidth(value: number) {
364
+    if (value < 0) return SprocketControl.DEFAULT_TICK_WIDTH;
365
+    return value;
366
+  }
367
+
368
+  private coerceLowestAlpha(value: number) {
369
+    if (value < SprocketControl.ALPHA_LOWER_LIMIT) return SprocketControl.ALPHA_LOWER_LIMIT;
370
+    if (value > SprocketControl.ALPHA_UPPER_LIMIT) return SprocketControl.ALPHA_UPPER_LIMIT;
371
+    return value;
372
+  }
373
+
374
+  private coerceAlphaTicksPercentage(value: number) {
375
+    if (value > 100) return 100;
376
+    if (value < SprocketControl.ALPHA_TICK_PERCENTAGE_LOWER_LIMIT) return SprocketControl.ALPHA_TICK_PERCENTAGE_LOWER_LIMIT;
377
+    return value;
378
+  }
379
+
380
+  // 销毁方法
381
+  dispose() {
382
+    this.stop();
383
+  }
384
+}

+ 135
- 0
ant-design-pro-vue3/src/views/front/platfrom/presentation/PageFunctions/TradePage.ts View File

@@ -0,0 +1,135 @@
1
+// 定义相关类型
2
+interface TradeModel {}
3
+interface PageContainer {}
4
+interface IPage {
5
+    Dispose(): void;
6
+    OwnerContainer: PageContainer;
7
+    SetOwnerContainer(pageContainer: PageContainer): void;
8
+    InstanceId: string;
9
+    SetInstanceId(guid: string): void;
10
+    ViewStateData: { [key: string]: any };
11
+    SetViewStateData(viewStateData: { [key: string]: any }): void;
12
+}
13
+
14
+interface EventHandler {
15
+    (sender: any, e: any): void;
16
+}
17
+
18
+interface PropertyChangedEventHandler {
19
+    (sender: any, e: { propertyName: string }): void;
20
+}
21
+
22
+// 模拟辅助类
23
+class PageHelper {
24
+    static GetTradeModel(sender: any): TradeModel {
25
+        return {} as TradeModel;
26
+    }
27
+    static SetTradeModel(sender: any, value: TradeModel) {}
28
+    static SetOwnerPage(sender: any, page: any) {}
29
+    static GetViewStateData(sender: any): { [key: string]: any } {
30
+        return {};
31
+    }
32
+    static SetViewStateData(sender: any, viewStateData: { [key: string]: any }) {}
33
+}
34
+
35
+class PageContainerHelper {
36
+    static GetOwnerContainer(sender: any): PageContainer {
37
+        return {} as PageContainer;
38
+    }
39
+    static SetOwnerContainer(sender: any, pageContainer: PageContainer) {}
40
+    static GetInstanceId(sender: any): string {
41
+        return "";
42
+    }
43
+    static SetInstanceId(sender: any, guid: string) {}
44
+}
45
+
46
+class TradePage implements IPage {
47
+    private _ready: EventHandler | null = null;
48
+    private _propertyChanged: PropertyChangedEventHandler | null = null;
49
+
50
+    constructor() {
51
+        // 模拟加载事件
52
+        this.triggerLoad();
53
+    }
54
+
55
+    get TradeModel(): TradeModel {
56
+        return PageHelper.GetTradeModel(this);
57
+    }
58
+
59
+    set TradeModel(value: TradeModel) {
60
+        PageHelper.SetTradeModel(this, value);
61
+    }
62
+
63
+    get Ready() {
64
+        return {
65
+            add: (handler: EventHandler) => {
66
+                this._ready = handler;
67
+            },
68
+            remove: (handler: EventHandler) => {
69
+                if (this._ready === handler) {
70
+                    this._ready = null;
71
+                }
72
+            },
73
+        };
74
+    }
75
+
76
+    private triggerLoad() {
77
+        PageHelper.SetOwnerPage(this, this);
78
+        if (this._ready) {
79
+            this._ready(this, {});
80
+        }
81
+        this.onTradePageLoaded();
82
+    }
83
+
84
+    protected onTradePageLoaded() {}
85
+
86
+    Dispose() {}
87
+
88
+    get OwnerContainer(): PageContainer {
89
+        return PageContainerHelper.GetOwnerContainer(this);
90
+    }
91
+
92
+    SetOwnerContainer(pageContainer: PageContainer) {
93
+        PageContainerHelper.SetOwnerContainer(this, pageContainer);
94
+    }
95
+
96
+    get InstanceId(): string {
97
+        return PageContainerHelper.GetInstanceId(this);
98
+    }
99
+
100
+    SetInstanceId(guid: string) {
101
+        PageContainerHelper.SetInstanceId(this, guid);
102
+    }
103
+
104
+    get ViewStateData(): { [key: string]: any } {
105
+        return PageHelper.GetViewStateData(this);
106
+    }
107
+
108
+    SetViewStateData(viewStateData: { [key: string]: any }) {
109
+        if (!viewStateData) {
110
+            viewStateData = {};
111
+        }
112
+        PageHelper.SetViewStateData(this, viewStateData);
113
+    }
114
+
115
+    get PropertyChanged() {
116
+        return {
117
+            add: (handler: PropertyChangedEventHandler) => {
118
+                this._propertyChanged = handler;
119
+            },
120
+            remove: (handler: PropertyChangedEventHandler) => {
121
+                if (this._propertyChanged === handler) {
122
+                    this._propertyChanged = null;
123
+                }
124
+            },
125
+        };
126
+    }
127
+
128
+    protected raisePropertyChanged(propertyName: string) {
129
+        if (this._propertyChanged) {
130
+            this._propertyChanged(this, { propertyName });
131
+        }
132
+    }
133
+}
134
+
135
+export default TradePage;

+ 50
- 0
ant-design-pro-vue3/src/views/front/platfrom/presentation/PagesHelper/PageContainerHelper.ts View File

@@ -0,0 +1,50 @@
1
+// 模拟 DependencyObject
2
+class DependencyObject {
3
+    // 这里只是简单模拟,实际可能需要更复杂的实现
4
+}
5
+
6
+// 模拟 PageContainer
7
+class PageContainer {
8
+    // 这里只是简单模拟,实际可能需要更复杂的实现
9
+}
10
+
11
+// 模拟 Guid
12
+class Guid {
13
+    static Empty = new Guid();
14
+}
15
+
16
+// 存储附加属性的值
17
+const attachedProperties = new WeakMap<DependencyObject, { [key: string]: any }>();
18
+
19
+export class PageContainerHelper {
20
+    private static readonly OwnerContainerKey = "OwnerContainer";
21
+    private static readonly InstanceIdKey = "InstanceId";
22
+
23
+    public static GetOwnerContainer(d: DependencyObject): PageContainer {
24
+        const props = attachedProperties.get(d);
25
+        return props ? props[this.OwnerContainerKey] as PageContainer : null;
26
+    }
27
+
28
+    public static SetOwnerContainer(d: DependencyObject, value: PageContainer): void {
29
+        let props = attachedProperties.get(d);
30
+        if (!props) {
31
+            props = {};
32
+            attachedProperties.set(d, props);
33
+        }
34
+        props[this.OwnerContainerKey] = value;
35
+    }
36
+
37
+    public static GetInstanceId(d: DependencyObject): Guid {
38
+        const props = attachedProperties.get(d);
39
+        return props ? props[this.InstanceIdKey] as Guid : Guid.Empty;
40
+    }
41
+
42
+    public static SetInstanceId(d: DependencyObject, value: Guid): void {
43
+        let props = attachedProperties.get(d);
44
+        if (!props) {
45
+            props = {};
46
+            attachedProperties.set(d, props);
47
+        }
48
+        props[this.InstanceIdKey] = value;
49
+    }
50
+}

+ 51
- 0
ant-design-pro-vue3/src/views/front/platfrom/presentation/PagesHelper/PageHelper.ts View File

@@ -0,0 +1,51 @@
1
+// 假设 IPage 接口定义如下
2
+interface IPage {}
3
+
4
+// 假设 TradeModel 类型定义如下
5
+interface TradeModel {}
6
+
7
+// 定义一个全局对象来存储附加属性的值
8
+const attachedProperties = new WeakMap<object, { [key: string]: any }>();
9
+
10
+function getAttachedProperty<T>(obj: object, propertyName: string): T | undefined {
11
+    const properties = attachedProperties.get(obj);
12
+    return properties?.[propertyName];
13
+}
14
+
15
+function setAttachedProperty(obj: object, propertyName: string, value: any) {
16
+    let properties = attachedProperties.get(obj);
17
+    if (!properties) {
18
+        properties = {};
19
+        attachedProperties.set(obj, properties);
20
+    }
21
+    properties[propertyName] = value;
22
+}
23
+
24
+export class PageHelper {
25
+    // OwnerPage 附加属性
26
+    static get OwnerPageProperty() { return "OwnerPage"; }
27
+    static GetOwnerPage(d: object): IPage | undefined {
28
+        return getAttachedProperty<IPage>(d, this.OwnerPageProperty);
29
+    }
30
+    static SetOwnerPage(d: object, value: IPage) {
31
+        setAttachedProperty(d, this.OwnerPageProperty, value);
32
+    }
33
+
34
+    // ViewStateData 附加属性
35
+    static get ViewStateDataProperty() { return "ViewStateData"; }
36
+    static GetViewStateData(obj: object): Record<string, object> | undefined {
37
+        return getAttachedProperty<Record<string, object>>(obj, this.ViewStateDataProperty);
38
+    }
39
+    static SetViewStateData(obj: object, value: Record<string, object>) {
40
+        setAttachedProperty(obj, this.ViewStateDataProperty, value);
41
+    }
42
+
43
+    // TradeModel 附加属性
44
+    static get TradeModelProperty() { return "TradeModel"; }
45
+    static GetTradeModel(obj: object): TradeModel | undefined {
46
+        return getAttachedProperty<TradeModel>(obj, this.TradeModelProperty);
47
+    }
48
+    static SetTradeModel(obj: object, value: TradeModel) {
49
+        setAttachedProperty(obj, this.TradeModelProperty, value);
50
+    }
51
+}

+ 8
- 0
ant-design-pro-vue3/src/views/front/platfrom/presentation/Themes/Generic.xaml View File

@@ -0,0 +1,8 @@
1
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
2
+                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
3
+                    xmlns:Presentation="clr-namespace:Platform.Presentation.PageFunctions">
4
+    <ResourceDictionary.MergedDictionaries>
5
+        <ResourceDictionary Source="/Platform.Presentation;component/Themes/PageContainer.Generic.xaml" />
6
+        <ResourceDictionary Source="/Platform.Presentation;component/Themes/TradePage.Generic.xaml"/>
7
+    </ResourceDictionary.MergedDictionaries>
8
+</ResourceDictionary>

+ 76
- 0
ant-design-pro-vue3/src/views/front/platfrom/presentation/Themes/PageContainer.Generic.xaml View File

@@ -0,0 +1,76 @@
1
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
2
+                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
3
+                    xmlns:dhcc="http://www.dhcc.com.cn"
4
+                    xmlns:Presentation="clr-namespace:Platform.Presentation.PageFunctions">
5
+    <dhcc:BoolToVisibilityConverter x:Key="BoolToVisibility" />
6
+
7
+    <Style TargetType="Presentation:PageContainer">
8
+        <!--  PageContainer不设置FocusManager.EnableFocusControl附加属性,延迟由TradePage来指定  -->
9
+        <!--  <Setter Property="dhcc:FocusManager.EnableFocusControl" Value="true"/>  -->
10
+        <Setter Property="VerticalAlignment" Value="Stretch" />
11
+        <Setter Property="HorizontalAlignment" Value="Stretch" />
12
+        <Setter Property="Template">
13
+            <Setter.Value>
14
+                <ControlTemplate TargetType="Presentation:PageContainer">
15
+                    <Border>
16
+                        <Grid>
17
+                            <AdornerDecorator>
18
+                                <ContentPresenter Margin="{TemplateBinding BorderThickness}"
19
+                                              HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
20
+                                              VerticalAlignment="{TemplateBinding VerticalAlignment}"
21
+                                              Content="{TemplateBinding Content}" />
22
+                            </AdornerDecorator>
23
+                            <Grid x:Name="Overlay"
24
+                                  Margin="0"
25
+                                  Background="#7F000000"
26
+                                  Opacity="1"
27
+                                  Visibility="{TemplateBinding IsOverlay, Converter={StaticResource BoolToVisibility}}" />
28
+                            <Border x:Name="BusyAdorner"
29
+                                    Tag="正在处理数据..."
30
+                                    Visibility="Collapsed">
31
+                                <Grid>
32
+                                    <Border Background="Black" Opacity="0.1" />
33
+                                    <!--  缓冲动画  -->
34
+                                    <Border HorizontalAlignment="Center"
35
+                                            VerticalAlignment="Center"
36
+                                            Background="White"
37
+                                            BorderBrush="Blue"
38
+                                            BorderThickness="2"
39
+                                            TextBlock.FontSize="20">
40
+                                        <StackPanel Margin="5" Orientation="Horizontal">
41
+                                            <Presentation:SprocketControl x:Name="sprocketControl"
42
+                                                                          Width="30"
43
+                                                                          Height="30"
44
+                                                                          HorizontalAlignment="Center"
45
+                                                                          VerticalAlignment="Top"
46
+                                                                          AlphaTicksPercentage="50"
47
+                                                                          Interval="100"
48
+                                                                          IsIndeterminate="False"
49
+                                                                          LowestAlpha="50"
50
+                                                                          StartAngle="-90"
51
+                                                                          TickColor="Blue"
52
+                                                                          TickCount="10"
53
+                                                                          TickWidth="3" />
54
+                                            <TextBlock VerticalAlignment="Center" Text="{Binding ElementName=BusyAdorner, Path=Tag}" />
55
+                                        </StackPanel>
56
+                                    </Border>
57
+                                </Grid>
58
+                            </Border>
59
+                        </Grid>
60
+                    </Border>
61
+                    <!--  不通过触发器触发缓冲动画  -->
62
+                    <!--
63
+                        <ControlTemplate.Triggers>
64
+                        <Trigger Property="IsBusy" Value="True">
65
+                        <Setter TargetName="cover" Property="Visibility" Value="Visible" />
66
+                        </Trigger>
67
+                        <Trigger Property="IsBusy" Value="False">
68
+                        <Setter TargetName="cover" Property="Visibility" Value="Collapsed" />
69
+                        </Trigger>
70
+                        </ControlTemplate.Triggers>
71
+                    -->
72
+                </ControlTemplate>
73
+            </Setter.Value>
74
+        </Setter>
75
+    </Style>
76
+</ResourceDictionary>

+ 29
- 0
ant-design-pro-vue3/src/views/front/platfrom/presentation/Themes/TradePage.Generic.xaml View File

@@ -0,0 +1,29 @@
1
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
2
+                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
3
+                    xmlns:Presentation="clr-namespace:Platform.Presentation.PageFunctions">
4
+    <Style TargetType="{x:Type Presentation:TradePage}">
5
+        <Setter Property="HorizontalContentAlignment" Value="Stretch" />
6
+        <!--<Setter Property="FocusManager.IsFocusScope" Value="True" />-->
7
+        <Setter Property="KeyboardNavigation.TabNavigation" Value="None" />
8
+        <Setter Property="VerticalContentAlignment" Value="Stretch" />       
9
+        <Setter Property="Template">
10
+            <Setter.Value>
11
+                <ControlTemplate TargetType="{x:Type Presentation:TradePage}">
12
+                    <Border Background="{TemplateBinding Background}"
13
+                            BorderBrush="{TemplateBinding BorderBrush}"
14
+                            BorderThickness="{TemplateBinding BorderThickness}">
15
+                        <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
16
+                                          VerticalAlignment="{TemplateBinding VerticalAlignment}"
17
+                                          Content="{TemplateBinding Content}" />
18
+                    </Border>
19
+                    <!--<ControlTemplate.Triggers>
20
+                        <EventTrigger RoutedEvent="Loaded">
21
+                            <BeginStoryboard Storyboard="{DynamicResource TradePage_Loaded_Storyboard}" />
22
+                        </EventTrigger>
23
+                    </ControlTemplate.Triggers>-->
24
+                </ControlTemplate>
25
+            </Setter.Value>
26
+        </Setter>
27
+        <!--<Setter Property="OpacityMask" Value="{DynamicResource TradePage_Transition_OpacityMask}" />-->
28
+    </Style>
29
+</ResourceDictionary>

Loading…
Cancel
Save