Esempio n. 1
0
        // 刷新显示
        // 把 actions 中的对象的状态变化更新到当前文档中
        // TODO: 一个办法是整个 Paragraph 替换。一个办法只替换里面的部分 InLine 对象
        // parameters:
        //      actions 发生了状态改变的 action。也就是被执行同步了的 action
        //      skipped 被跳过了(没有处理的) action
        public void Refresh(List <ActionInfo> actions)
        {
            // 更新 _actions 中的对象
            int count = 0;

            foreach (var action in actions)
            {
                var old_action = _actions.Where(o => o.ID == action.ID).FirstOrDefault();
                if (old_action != null)
                {
                    int index = _actions.IndexOf(old_action);
                    Debug.Assert(index != -1, "");
                    if (index != -1)
                    {
                        _actions.RemoveAt(index);
                        _actions.Insert(index, action);
                        count++;
                    }
                }
            }

            if (count == 0)
            {
                return;
            }

            {
                // 检查超额图书
                List <string> overflow_titles = new List <string>();
                _actions.ForEach(item =>
                {
                    if (item.Action == "borrow" && item.SyncErrorCode == "overflow")
                    {
                        overflow_titles.Add($"{ShortTitle(item.Entity.Title)} [{ShelfData.GetPiiString(item.Entity)}]");
                    }
                });

                // 显示超额的信息
                if (overflow_titles.Count > 0)
                {
                    // 定位 Paragraph
                    var block = this.Blocks.Where(o =>
                    {
                        if (!(o.Tag is string id))
                        {
                            return(false);
                        }
                        return(id == OVERFLOW_ID);
                    }).FirstOrDefault();

                    // block 不应为 null。替代方法:
                    if (block == null)
                    {
                        // TODO: 在适当位置插入标志段落
                        throw new Exception("#overflow 标志段落没有找到");
                    }

                    var p = BuildOverflowParagraph(overflow_titles);
                    this.Blocks.InsertBefore(block, p);
                    this.Blocks.Remove(block);

                    // 获得人名
                    List <string> names = new List <string>();
                    {
                        actions.ForEach((o) =>
                        {
                            if (o.Operator != null)
                            {
                                names.Add(string.IsNullOrEmpty(o.Operator.PatronName) ? o.Operator.PatronBarcode : o.Operator.PatronName);
                            }
                        });
                        StringUtil.RemoveDupNoSort(ref names);
                    }

                    // 语音提醒
                    // 针对同一个人,短时间内密集提醒要注意避免
                    if (HasOverflowSpeaked(StringUtil.MakePathList(names), TimeSpan.FromSeconds(30)) == false)
                    {
                        App.CurrentApp.SpeakSequence("警告:借书超额");
                    }
                }
            }

            foreach (var action in actions)
            {
                // 定位 Paragraph
                var block = this.Blocks.Where(o =>
                {
                    if (!(o.Tag is ParagraphInfo info))
                    {
                        return(false);
                    }
                    return(info.Action.ID == action.ID);
                })
                            .FirstOrDefault();
                if (block == null)
                {
                    continue;
                }

                // 替换 Paragraph
                {
                    if (!(block.Tag is ParagraphInfo old_info))
                    {
                        continue;
                    }

                    var new_block = BuildParagraph(action, old_info.Index, this.BaseFontSize, this.BuildStyle);
                    this.Blocks.InsertBefore(block, new_block);
                    this.Blocks.Remove(block);
                }
            }
        }
Esempio n. 2
0
        public static SubmitDocument Build(List <ActionInfo> actions,
                                           double baseFontSize,
                                           string style)
        {
            SubmitDocument doc = new SubmitDocument();

            doc.BaseFontSize = baseFontSize;
            doc.BuildStyle   = style;

            // 保存起来
            doc._actions.Clear();
            doc._actions.AddRange(actions);

            bool display_transfer = StringUtil.IsInList("transfer", style);

            // 第一部分,总结信息
            List <string> names = new List <string>();
            {
                actions.ForEach((o) =>
                {
                    if (o.Operator != null)
                    {
                        names.Add(string.IsNullOrEmpty(o.Operator.PatronName) ? o.Operator.PatronBarcode : o.Operator.PatronName);
                    }
                });
                StringUtil.RemoveDupNoSort(ref names);
            }

            int return_count = actions.FindAll((o) => { return(o.Action == "return"); }).Count;
            int borrow_count = actions.FindAll((o) => { return(o.Action == "borrow"); }).Count;

            // 修改了 currentLocation 并且向内转移的数量
            int change_currentLocation_count = actions
                                               .FindAll((o) =>
            {
                return(o.Action.StartsWith("transfer") &&
                       string.IsNullOrEmpty(o.CurrentShelfNo) == false &&
                       o.TransferDirection == "in");
            })
                                               .Count;

            // 修改了 location 的数量。这个意味着发生了调拨
            int change_location_count = actions
                                        .FindAll(o => { return(o.Action.StartsWith("transfer") && string.IsNullOrEmpty(o.Location) == false); })
                                        .Count;

            // (工作人员)普通下架。特点是去向不明,但至少知道这些图书是离开书柜了
            int transferout_count = actions
                                    .FindAll(o => { return(o.Action.StartsWith("transfer") && o.TransferDirection == "out"); })
                                    .Count;

            // 总结一下涉及到的门
            var door_names = ShelfData.GetDoorName(actions);

            /*
             * int succeed_count = actions.FindAll((o) => { return o.ResultType == "succeed" || string.IsNullOrEmpty(o.ResultType); }).Count;
             * int error_count = items.FindAll((o) => { return o.ResultType == "error"; }).Count;
             * int warning_count = items.FindAll((o) => { return o.ResultType == "warning"; }).Count;
             * int information_count = 0;
             * if (display_transfer == false)
             *  information_count = items.FindAll((o) => { return o.ResultType == "information" && o.Operation != "transfer"; }).Count;
             * else
             *  information_count = items.FindAll((o) => { return o.ResultType == "information"; }).Count;
             *
             * // 检查超额图书
             * List<string> overflow_titles = new List<string>();
             * items.ForEach(item =>
             * {
             *  if (item.Operation == "borrow" && item.ErrorCode == "overflow")
             *      overflow_titles.Add($"{ShortTitle(item.Entity.Title)} [{item.Entity.PII}]");
             * });
             */

            {
                var p = new Paragraph();
                p.FontFamily    = new FontFamily("微软雅黑");
                p.FontSize      = baseFontSize;
                p.TextAlignment = TextAlignment.Center;
                p.Foreground    = Brushes.Gray;
                // p.TextIndent = -20;
                p.Margin = new Thickness(0, 0, 0, baseFontSize /*18*/);
                doc.Blocks.Add(p);

                if (borrow_count
                    + return_count
                    + change_currentLocation_count
                    + change_location_count
                    + transferout_count > 0)
                {
                    List <string> lines = new List <string>();
                    if (return_count > 0)
                    {
                        lines.Add($"还书 {return_count}");
                    }
                    if (borrow_count > 0)
                    {
                        lines.Add($"借书 {borrow_count}");
                    }

REDO:
                    if (display_transfer && change_currentLocation_count > 0)
                    {
                        lines.Add($"上架 {change_currentLocation_count}");
                    }
                    if (display_transfer && change_location_count > 0)
                    {
                        lines.Add($"调拨 {change_location_count}");
                    }
                    if (display_transfer && transferout_count > 0)
                    {
                        lines.Add($"下架 {transferout_count}");
                    }

                    if (lines.Count == 0 && display_transfer == false)
                    {
                        display_transfer = true;

                        // 修正 style,便于 Refresh() 时候使用新的 style
                        StringUtil.SetInList(ref style, "transfer", true);
                        doc.BuildStyle = style;
                        goto REDO;
                    }

                    p.Inlines.Add(new Run
                    {
                        Text = $"{StringUtil.MakePathList(names)}",
                        //Background = Brushes.DarkRed,
                        //Foreground = Brushes.White
                        FontFamily = new FontFamily("楷体"),
                        FontSize   = baseFontSize * 5.5, // 3.5,
                        // FontWeight = FontWeights.Bold,
                        Foreground = Brushes.White,
                    });

                    if (door_names.Count > 0)
                    {
                        p.Inlines.Add(new Run
                        {
                            Text = $"\r\n({StringUtil.MakePathList(door_names)})",
                            //Background = Brushes.DarkRed,
                            Foreground = Brushes.Green,
                            // FontFamily = new FontFamily("楷体"),
                            FontSize = baseFontSize * 2.0,    // 1.0
                            // FontWeight = FontWeights.Bold,
                        });
                    }

                    p.Inlines.Add(new Run
                    {
                        Text = $"\r\n{StringUtil.MakePathList(lines, ", ")}\r\n",
                        //Background = Brushes.DarkRed,
                        //Foreground = Brushes.White
                        FontSize   = baseFontSize * 3.0, // * 1.2,
                        Foreground = Brushes.White,
                    });

                    App.CurrentApp.SpeakSequence(StringUtil.MakePathList(lines, ", "));
                }

#if NO
                if (error_count > 0)
                {
                    p.Inlines.Add(new Run
                    {
                        Text       = $" 错误 {error_count} ",
                        Background = Brushes.DarkRed,
                        Foreground = Brushes.White
                    });
                }
                if (warning_count > 0)
                {
                    p.Inlines.Add(new Run
                    {
                        Text       = $" 警告 {warning_count} ",
                        Background = Brushes.DarkGoldenrod,
                        Foreground = Brushes.White
                    });
                }
                if (information_count > 0)
                {
                    p.Inlines.Add(new Run
                    {
                        Text       = $" 信息 {information_count} ",
                        Background = Brushes.Gray,
                        Foreground = Brushes.White
                    });
                }
                if (succeed_count > 0)
                {
                    p.Inlines.Add(new Run
                    {
                        Text       = $" 成功 {succeed_count} ",
                        Background = Brushes.DarkGreen,
                        Foreground = Brushes.White
                    });
                }
#endif
            }

#if NO
            // 第二部分,列出超额的信息
            if (overflow_titles.Count > 0)
            {
                var p = BuildOverflowParagraph(overflow_titles);
                doc.Blocks.Add(p);
            }
#endif
            // 检查超额图书
            List <string> overflow_titles = new List <string>();
            actions.ForEach(item =>
            {
                if (item.Action == "borrow" && item.SyncErrorCode == "overflow")
                {
                    overflow_titles.Add($"{ShortTitle(item.Entity.Title)} [{ShelfData.GetPiiString(item.Entity)}]");
                }
            });

            // 显示超额的信息
            if (overflow_titles.Count > 0)
            {
                var p = doc.BuildOverflowParagraph(overflow_titles);
                // p.Tag = "#overflow";
                doc.Blocks.Add(p);

                // 语音提醒
                App.CurrentApp.SpeakSequence("警告:借书超额");
            }
            else
            {
                // 超额信息的占位符
                var p = new Paragraph();
                p.FontSize = 0.1;
                p.Margin   = new Thickness();
                p.Padding  = new Thickness();
                p.Tag      = OVERFLOW_ID; // "#overflow";
                doc.Blocks.Add(p);
            }

            // 第三部分,列出每一笔操作
            int index = 0;
            foreach (var action in actions)
            {
                var p = BuildParagraph(action, index, baseFontSize, style);
                if (p != null)
                {
                    doc.Blocks.Add(p);
                    index++;
                }
            }

#if NO
            // 构造提示语音
            List <string> speaks = new List <string>();
            if (overflow_titles.Count > 0)
            {
                speaks.Add($"警告:有 {overflow_titles.Count} 册图书超越许可册数,请放回书柜,谢谢");
            }

            if (speaks.Count == 0)
            {
                speaks.Add("操作完成"); // TODO:可否增加姓名和借还册数?例如 王立文借书 5 册成功
            }
            speak = StringUtil.MakePathList(speaks, "; ");
#endif

            return(doc);
        }
Esempio n. 3
0
        public static Paragraph BuildParagraph(
            ActionInfo action,
            int index,
            double baseFontSize,
            string style)
        {
            // 是否显示 transfer (in) 条目。注意,即便 false, 也要显示 transfer (out) 条目的
            bool display_transfer = StringUtil.IsInList("transfer", style);

            if (action.Action.StartsWith("transfer") && action.TransferDirection == "in" &&
                display_transfer == false)
            {
                return(null);
            }

            var p = new Paragraph();

            p.FontFamily = new FontFamily("微软雅黑");
            p.FontSize   = baseFontSize;
            // p.FontStyle = FontStyles.Italic;
            p.TextAlignment = TextAlignment.Left;
            p.Foreground    = Brushes.Gray;
            // p.LineHeight = 18;
            p.TextIndent = -20;
            p.Margin     = new Thickness(10, 0, 0, 8); // 10,0,0,8
            p.Tag        = new ParagraphInfo {
                Action = action, Index = index
            };                                                              // 记忆下来后面刷新事项的时候可以用到

            // 序号
            p.Inlines.Add(new Run($"{(index + 1).ToString()}) "));

            Brush back = Brushes.Transparent;

            // 状态
            {
                // 等待动画
                if (string.IsNullOrEmpty(action.State))
                {
                    var image = new FontAwesome.WPF.ImageAwesome();
                    image.Icon         = FontAwesome.WPF.FontAwesomeIcon.Spinner;
                    image.Spin         = true;
                    image.SpinDuration = 5;
                    image.Height       = baseFontSize * 2.0;
                    image.Foreground   = Brushes.DarkGray;
                    var container = new InlineUIContainer(image);
                    container.Name = "image_id";
                    p.Inlines.Add(container);
                }
                else if (action.SyncErrorCode == "overflow")
                {
                    back = Brushes.DarkRed;
                    p.Inlines.Add(new Run
                    {
                        Text       = " 超额 ",
                        Background = back,
                        Foreground = Brushes.White
                    });
                }
                else if (action.State == "sync")
                {
                    back = Brushes.DarkGreen;
                    p.Inlines.Add(new Run
                    {
                        Text       = " 成功 ",
                        Background = back,
                        Foreground = Brushes.White
                    });
                }
                else if (action.SyncErrorCode == "skipped")
                {
                    back = Brushes.DeepSkyBlue;
                    p.Inlines.Add(new Run
                    {
                        Text       = $" 暂时跳过同步 ",
                        Background = back,
                        Foreground = Brushes.White
                    });
                }
                else if (action.State == "commerror" || action.State == "normalerror")
                {
                    if (ShelfData.LibraryNetworkCondition == "Bad")
                    {
                        back = Brushes.DeepSkyBlue;
                    }
                    else
                    {
                        back = Brushes.DarkRed;
                    }
                    p.Inlines.Add(new Run
                    {
                        Text       = $" 同步失败({action.State}) ",
                        Background = back,
                        Foreground = Brushes.White
                    });
                }
                else if (action.State == "dontsync")
                {
                    back = Brushes.DarkBlue;
                    p.Inlines.Add(new Run
                    {
                        Text       = $" 不再同步 ",
                        Background = back,
                        Foreground = Brushes.White
                    });
                }
                else
                {
                    back = Brushes.DarkRed;
                    p.Inlines.Add(new Run
                    {
                        Text       = $" {action.State} ",
                        Background = back,
                        Foreground = Brushes.White
                    });
                }
            }

            // 转移方向
            if (action.Action.StartsWith("transfer")
                /*&& string.IsNullOrEmpty(action.TransferDirection) == false*/)
            {
                p.Inlines.Add(new Run
                {
                    Text       = GetTransferDirCaption(action.TransferDirection, action.Location) + " ",
                    Foreground = Brushes.White
                });
            }
            else
            {
                // 操作名称
                p.Inlines.Add(new Run
                {
                    Text       = GetOperationCaption(action.Action) + " ",
                    Foreground = Brushes.White
                });
            }

            string title = "";

            if (action.Entity != null)
            {
                title = MessageDocument.ShortTitle(action.Entity.Title);
                // 2020/5/6
                // 尝试从本地缓存中获取书目摘要
                if (string.IsNullOrEmpty(title))
                {
                    title = LibraryChannelUtil.GetBiblioSummaryFromLocal(action.Entity.GetOiPii(true));
                }
                if (string.IsNullOrEmpty(title))
                {
                    title = ShelfData.GetPiiString(action.Entity);
                }
                else
                {
                    // 2020/7/22
                    title = $"[{ShelfData.GetPiiString(action.Entity)}] {title}";
                }
            }
            else
            {
                title = "(action.Entity 为空)";
            }

            // 书目摘要
            if (string.IsNullOrEmpty(title) == false)
            {
                Run run = new Run(title);

                /*
                 * run.FontSize = 14;
                 * run.FontStyle = FontStyles.Normal;
                 * run.Background = Brushes.DarkRed;
                 * run.Foreground = Brushes.White;
                 */

                p.Inlines.Add(run);
            }

            // 对于上架/下架来说,还要补充显示一些细节信息:location 去向;和 currentLocation 去向
            if (action.Action.StartsWith("transfer"))
            {
                List <string> details = new List <string>();
                if (string.IsNullOrEmpty(action.Location) == false)
                {
                    details.Add($"调拨到:{action.Location}");
                }
                if (string.IsNullOrEmpty(action.CurrentShelfNo) == false)
                {
                    details.Add($"新架位:{action.CurrentShelfNo}");
                }
                p.Inlines.Add(new Run
                {
                    Text       = " " + StringUtil.MakePathList(details, " ") + " ",
                    Foreground = Brushes.Green
                });
            }

            // 错误码和错误信息
            if (string.IsNullOrEmpty(action.SyncErrorInfo) == false &&
                (action.State != "sync" || action.SyncErrorCode == "overflow"))
            {
                p.Inlines.Add(new Run
                {
                    Text       = "\r\n" + action.SyncErrorInfo,
                    Background = back,
                    Foreground = Brushes.White
                });
            }

            return(p);
        }
Esempio n. 4
0
        // 刷新显示
        // 把 actions 中的对象的状态变化更新到当前文档中
        // TODO: 一个办法是整个 Paragraph 替换。一个办法只替换里面的部分 InLine 对象
        // parameters:
        //      actions 发生了状态改变的 action。也就是被执行同步了的 action
        //      skipped 被跳过了(没有处理的) action
        public void Refresh(List <ActionInfo> actions)
        {
            // 更新 _actions 中的对象
            int count = 0;

            foreach (var action in actions)
            {
                var old_action = _actions.Where(o => o.ID == action.ID).FirstOrDefault();
                if (old_action != null)
                {
                    int index = _actions.IndexOf(old_action);
                    Debug.Assert(index != -1, "");
                    if (index != -1)
                    {
                        _actions.RemoveAt(index);
                        _actions.Insert(index, action);
                        count++;
                    }
                }
            }

            if (count == 0)
            {
                return;
            }

            {
                // 检查超额图书
                List <string> overflow_titles = new List <string>();
                _actions.ForEach(item =>
                {
                    if (item.Action == "borrow" && item.SyncErrorCode == "overflow")
                    {
                        overflow_titles.Add($"{ShortTitle(item.Entity.Title)} [{ShelfData.GetPiiString(item.Entity)}]");
                    }
                });

                // 显示超额的信息
                if (overflow_titles.Count > 0)
                {
                    // 定位 Paragraph
                    var block = this.Blocks.Where(o =>
                    {
                        if (!(o.Tag is string id))
                        {
                            return(false);
                        }
                        return(id == OVERFLOW_ID);
                    }).FirstOrDefault();

                    // block 不应为 null。替代方法:
                    if (block == null)
                    {
                        // TODO: 在适当位置插入标志段落
                        throw new Exception("#overflow 标志段落没有找到");
                    }

                    var p = BuildOverflowParagraph(overflow_titles);
                    this.Blocks.InsertBefore(block, p);
                    this.Blocks.Remove(block);

                    // 语音提醒
                    App.CurrentApp.SpeakSequence("警告:借书超额");
                }
            }

            foreach (var action in actions)
            {
                // 定位 Paragraph
                var block = this.Blocks.Where(o =>
                {
                    if (!(o.Tag is ParagraphInfo info))
                    {
                        return(false);
                    }
                    return(info.Action.ID == action.ID);
                })
                            .FirstOrDefault();
                if (block == null)
                {
                    continue;
                }

                // 替换 Paragraph
                {
                    if (!(block.Tag is ParagraphInfo old_info))
                    {
                        continue;
                    }

                    var new_block = BuildParagraph(action, old_info.Index, this.BaseFontSize, this.BuildStyle);
                    this.Blocks.InsertBefore(block, new_block);
                    this.Blocks.Remove(block);
                }
            }
        }