示例#1
0
        /*
         * public void SetBooks(List<Entity> entities)
         * {
         *  EntityCollection collection = new EntityCollection();
         *  foreach(var entity in entities)
         *  {
         *      // TODO: 是否克隆 Entity?
         *      entity.Container = collection;
         *      collection.Add(entity);
         *  }
         *  books.SetSource(collection);
         * }
         */

        public void SetBooks(EntityCollection collection)
        {
            books.SetSource(collection);

            // 后台处理刷新
            var task = ShelfData.FillBookFields(collection, _cancel.Token, false);
        }
示例#2
0
        /*
         * public void SetBooks(List<Entity> entities)
         * {
         *  EntityCollection collection = new EntityCollection();
         *  foreach(var entity in entities)
         *  {
         *      // TODO: 是否克隆 Entity?
         *      entity.Container = collection;
         *      collection.Add(entity);
         *  }
         *  books.SetSource(collection);
         * }
         */

        public void SetBooks(EntityCollection collection)
        {
            books.SetSource(collection);

            // 后台处理刷新
            var task = ShelfData.FillBookFieldsAsync(collection, _cancel.Token, "refreshData" /*, false*/);
        }
示例#3
0
        // 将指定门的暂存的信息保存为 Action。但并不立即提交
        public async static Task SaveDoorActions(DoorItem door, bool clearOperator)
        {
            var result = await ShelfData.SaveActions((entity) =>
            {
                var results = DoorItem.FindDoors(ShelfData.Doors, entity.ReaderName, entity.Antenna);
                // TODO: 如果遇到 results.Count > 1 是否抛出异常?
                if (results.Count > 1)
                {
                    WpfClientInfo.WriteErrorLog($"读卡器名 '{entity.ReaderName}' 天线编号 {entity.Antenna} 匹配上 {results.Count} 个门");
                    throw new Exception($"读卡器名 '{entity.ReaderName}' 天线编号 {entity.Antenna} 匹配上 {results.Count} 个门。请检查 shelf.xml 并修正配置此错误,确保只匹配一个门");
                }

                if (results.IndexOf(door) != -1)
                {
                    return(door.Operator);
                    // return GetOperator(entity);
                }
                return(null);
            });

            if (result.Value == -1)
            {
                SetGlobalError("save_actions", $"SaveDoorActions() 出错: {result.ErrorInfo}");
                PageShelf.TrySetMessage(null, $"SaveDoorActions() 出错: {result.ErrorInfo}。这是一个严重错误,请管理员及时介入处理");
            }
            else
            {
                SetGlobalError("save_actions", null);
            }

            // 2019/12/21
            if (clearOperator == true && door.State == "close")
            {
                door.Operator = null; // 清掉门上的操作者名字
            }
        }
示例#4
0
        // 从 _entityList 中取出一批事项进行处理。由于是复制出来处理的,所以整个处理过程中(除了取出和最后删除的瞬间)不用对 _entityList 加锁
        // 对每一个事项,要进行如下处理:
        //  1) 获得册记录和书目摘要
        //  2) 尝试请求还书
        //  3) 请求设置 UID
        //  4) 修改 currentLocation 和 location
        static async Task ProcessingAsync()
        {
            var list = CopyList();

            foreach (var state in list)
            {
                // state.State = "???";
                try
                {
                    if (state.NewState == "open")
                    {
                        continue;
                    }

                    Debug.Assert(state.NewState == "close");

                    List <ActionInfo> actions = null;

                    try
                    {
                        DateTime start = DateTime.Now;

                        var result = await ShelfData.RefreshInventoryAsync(state.Door);

                        WpfClientInfo.WriteInfoLog($"针对门 {state.Door.Name} 执行 RefreshInventoryAsync() 耗时 {(DateTime.Now - start).TotalSeconds.ToString()}");

                        start = DateTime.Now;

                        // 2020/4/21 把这两句移动到 try 范围内
                        await SaveDoorActions(state.Door, true);

                        WpfClientInfo.WriteInfoLog($"针对门 {state.Door.Name} 执行 SaveDoorActions() 耗时 {(DateTime.Now - start).TotalSeconds.ToString()}");

                        start = DateTime.Now;

                        actions = ShelfData.PullActions();
                        WpfClientInfo.WriteInfoLog($"针对门 {state.Door.Name} 执行 PullActions() 耗时 {(DateTime.Now - start).TotalSeconds.ToString()}");
                    }
                    finally
                    {
                        state.Door.DecWaiting();
                        //WpfClientInfo.WriteInfoLog($"--decWaiting() door '{e.Door.Name}' state changed");
                    }


                    // 注: 调用完成后门控件上的 +- 数字才会消失
                    var task = PageMenu.PageShelf.DoRequestAsync(actions, "");

                    App.SetError("processing", null);
                }
                catch (Exception ex)
                {
                    WpfClientInfo.WriteErrorLog($"ProcessingAsync() 出现异常: {ExceptionUtil.GetDebugText(ex)}");
                    App.SetError("processing", $"ProcessingAsync() 出现异常: {ex.Message}");
                }
                finally
                {
                    // state.State = "";
                }
            }

            // 把处理过的 entity 从 list 中移走
            RemoveList(list);

            // 2020/11/21
            // 如果发现队列里面又有新的对象,则立即激活任务
            if (GetListCount() > 0)
            {
                ActivateTask();
            }
        }
示例#5
0
        // return.Value:
        //      -1  出错
        //      0   读者记录没有找到
        //      1   成功
        public static GetReaderInfoResult GetReaderInfo(string pii)
        {
            /*
             * reader_xml = "";
             * recpath = "";
             * timestamp = null;
             */
            if (string.IsNullOrEmpty(App.dp2ServerUrl) == true)
            {
                return new GetReaderInfoResult
                       {
                           Value     = -1,
                           ErrorInfo = "dp2library 服务器 URL 尚未配置,无法获得读者信息"
                       }
            }
            ;
            LibraryChannel channel     = App.CurrentApp.GetChannel();
            var            old_timeout = channel.Timeout;

            channel.Timeout = TimeSpan.FromSeconds(5);  // 设置 5 秒超时,避免等待太久
            try
            {
                int nRedoCount = 0;

REDO:
                long lRet = channel.GetReaderInfo(null,
                                                  pii,
                                                  "advancexml", // "xml",
                                                  out string[] results,
                                                  out string recpath,
                                                  out byte[] timestamp,
                                                  out string strError);
                if (lRet == -1 || lRet == 0)
                {
                    // 2020/4/24 增加一次重试机会
                    if (lRet == -1 &&
                        (channel.ErrorCode == ErrorCode.RequestCanceled || channel.ErrorCode == ErrorCode.RequestError) &&
                        nRedoCount < 2)
                    {
                        nRedoCount++;

                        goto REDO;
                    }

                    // 如果发生通讯失败,则主动重新探测一次网络状况
                    if (channel.ErrorCode == ErrorCode.RequestCanceled || channel.ErrorCode == ErrorCode.RequestError)
                    {
                        ShelfData.DetectLibraryNetwork();
                    }

                    return(new GetReaderInfoResult
                    {
                        Value = (int)lRet,
                        ErrorInfo = strError,
                        RecPath = recpath,
                        Timestamp = timestamp
                    });
                }

                // 2019/12/19
                // 命中读者记录多于一条
                if (lRet > 1)
                {
                    return(new GetReaderInfoResult
                    {
                        Value = -1,
                        ErrorInfo = $"装载读者记录失败:'{pii}' 检索命中读者记录 {lRet} 条"
                    });
                }

                string reader_xml = "";
                if (results != null && results.Length > 0)
                {
                    reader_xml = results[0];
                }
                return(new GetReaderInfoResult
                {
                    Value = 1,
                    RecPath = recpath,
                    Timestamp = timestamp,
                    ReaderXml = reader_xml
                });
            }
            finally
            {
                channel.Timeout = old_timeout;
                App.CurrentApp.ReturnChannel(channel);
            }
        }
示例#6
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);
                }
            }
        }
示例#7
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);
        }
示例#8
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);
        }
示例#9
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);
                }
            }
        }
示例#10
0
 public static bool GetBackLampState()
 {
     return(ShelfData.GetLampState("back"));
 }
示例#11
0
 public static void TurnBackLampOff()
 {
     ShelfData.TurnLamp("back", "off");
 }
示例#12
0
 public static void TurnBackLampOn()
 {
     ShelfData.TurnLamp("back", "on");
 }