Пример #1
0
        /// <summary>
        /// 根据sql、过滤条件获取数据源,sql必须含有服务名前缀,如:
        /// Cm:select * from dt_log
        /// local:select * from letter
        /// </summary>
        /// <param name="p_sql">带前缀的sql</param>
        /// <param name="p_filter"></param>
        /// <returns></returns>
        static async Task <Table> GetDataBySql(string p_sql, string p_filter = null)
        {
            if (string.IsNullOrEmpty(p_sql))
            {
                return(null);
            }

            string[] info = p_sql.Trim().Split(':');
            if (info.Length != 2 || string.IsNullOrEmpty(info[0]) || string.IsNullOrEmpty(info[1]))
            {
                throw new Exception("Sql格式不正确!" + p_sql);
            }

            Table  data;
            string sql = string.IsNullOrEmpty(p_filter) ? info[1] : $"select * from ({info[1]}) a where {p_filter}";

            if (info[0].ToLower() == "local")
            {
                data = AtState.Query(sql);
            }
            else
            {
                data = await new UnaryRpc(info[0], "Da.Query", sql, null).Call <Table>();
            }
            return(data);
        }
Пример #2
0
        /// <summary>
        /// 设置自启动
        /// </summary>
        /// <param name="p_win"></param>
        internal static void SetAutoStart(Win p_win)
        {
            if (p_win == null)
            {
                return;
            }

            if (!Kit.IsPhoneUI)
            {
                Tabs tabs = (Tabs)p_win.GetValue(Win.MainTabsProperty);
                if (tabs != null &&
                    tabs.Items.Count > 0 &&
                    ((Tab)tabs.Items[0]).Content is Win win)
                {
                    // 设置主区窗口为自启动
                    p_win = win;
                }
            }

            AutoStartInfo info = new AutoStartInfo();

            info.WinType = p_win.GetType().AssemblyQualifiedName;
            info.Title   = p_win.Title;
            info.Icon    = p_win.Icon.ToString();
            if (p_win.Params != null)
            {
                info.Params     = JsonSerializer.Serialize(p_win.Params, JsonOptions.UnsafeSerializer);
                info.ParamsType = p_win.Params.GetType().AssemblyQualifiedName;
            }
            AtState.SaveAutoStart(info);
            Kit.Msg(string.Format("{0}已设置自启动!", p_win.Title));
        }
Пример #3
0
        /// <summary>
        /// 获取用户可访问的菜单
        /// </summary>
        /// <returns></returns>
        static async Task <List <long> > GetAllUserMenus()
        {
            int cnt = AtState.GetScalar <int>("select count(*) from DataVersion where id='menu'");

            if (cnt == 0)
            {
                // 查询服务端
                Dict dt = await AtCm.GetMenus(Kit.UserID);

                // 记录版本号
                var ver = new DataVersion(ID: "menu", Ver: dt.Str("ver"));
                await AtState.Save(ver, false);

                // 清空旧数据
                AtState.Exec("delete from UserMenu");

                // 插入新数据
                var ls = (List <long>)dt["result"];
                if (ls != null && ls.Count > 0)
                {
                    List <Dict> dts = new List <Dict>();
                    foreach (var id in ls)
                    {
                        dts.Add(new Dict {
                            { "id", id }
                        });
                    }
                    AtState.BatchExec("insert into UserMenu (id) values (:id)", dts);
                }
                return(ls);
            }

            return(AtState.FirstCol <long>("select id from UserMenu"));
        }
Пример #4
0
 void OnUploadFinished(object sender, bool suc)
 {
     if (suc)
     {
         AtState.SaveCookie("FileTransDemo", _fl.Data);
     }
 }
Пример #5
0
        void OnDelMsg(object sender, Mi e)
        {
            var l = (Letter)e.DataContext;

            AtState.Exec($"delete from Letter where ID={l.ID}");
            _lv.Data.Remove(l);
        }
Пример #6
0
        /// <summary>
        /// 分页加载信息
        /// </summary>
        /// <param name="e"></param>
        void OnNextPage(PageData e)
        {
            int cnt = AtState.GetScalar <int>("select count(*) from Letter where otherid=@otherid and loginid=@loginid",
                                              new Dict
            {
                { "otherid", OtherID },
                { "loginid", Kit.UserID }
            });

            int start = cnt - (e.PageNo + 1) * e.PageSize;
            int limit = e.PageSize;

            if (start < 0)
            {
                limit = cnt - e.PageNo * e.PageSize;
            }

            Nl <Letter> data = new Nl <Letter>();
            var         ls   = AtState.Each <Letter>($"select * from Letter where otherid={OtherID} and loginid={Kit.UserID} order by stime limit {limit} offset {start}");

            foreach (var l in ls)
            {
                var photo = l.IsReceived ? _other.Photo : Kit.UserPhoto;
                if (string.IsNullOrEmpty(photo))
                {
                    photo = "photo/profilephoto.jpg";
                }
                l.Photo = photo;
                data.Add(l);
            }
            e.LoadPageData(data);
        }
Пример #7
0
        /// <summary>
        /// 加载信息
        /// </summary>
        async void LoadMsg()
        {
            if (OtherID < 0)
            {
                return;
            }

            string sql = $"select * from ChatMember where id={OtherID}";

            _other = AtState.First <ChatMember>(sql);
            if (_other == null)
            {
                // 初次打开,还未下载好友列表
                await FriendMemberList.Refresh();

                _other = AtState.First <ChatMember>(sql);

                // 不在好友列表时,创建虚拟
                if (_other == null)
                {
                    _other = new ChatMember(
                        ID: OtherID,
                        Name: OtherID.ToString(),
                        Photo: "photo/profilephoto.jpg");
                }
            }

            // 不是好友时无法发送
            //_inputBar.Visibility = (_other == null) ? Visibility.Collapsed : Visibility.Visible;

            LetterManager.ClearUnreadFlag(OtherID);
            _lv.PageData = new PageData {
                NextPage = OnNextPage, InsertTop = true
            };
        }
Пример #8
0
        /// <summary>
        /// 更新好友列表,默认超过10小时需要刷新
        /// </summary>
        /// <returns></returns>
        public static async Task Refresh()
        {
            if (!NeedRefresh())
            {
                return;
            }

            // 暂时取所有,后续增加好友功能
            var tbl = await new UnaryRpc(
                "cm",
                "Da.Query",
                "select id,name,phone,sex,(case photo when '' then 'photo/profilephoto.jpg' else photo end) as photo, mtime from cm_user"
                ).Call <Table <ChatMember> >();

            // 将新列表缓存到本地库
            AtState.Exec("delete from ChatMember");
            if (tbl != null && tbl.Count > 0)
            {
                foreach (var r in tbl)
                {
                    r.IsAdded = true;
                }
                await AtState.BatchSave(tbl, false);
            }

            // 记录刷新时间
            AtState.SaveCookie(_refreshKey, Kit.Now.ToString());
        }
Пример #9
0
        void LoadHisItems()
        {
            var his = AtState.Each <SearchFvHis>($"select * from SearchFvHis where BaseUri='{_baseUri}' order by id desc");

            foreach (var item in his)
            {
                Grid grid = new Grid();
                grid.ColumnDefinitions.Add(new ColumnDefinition {
                    Width = new GridLength(1, GridUnitType.Star)
                });
                grid.ColumnDefinitions.Add(new ColumnDefinition {
                    Width = GridLength.Auto
                });
                grid.DataContext = item;

                Button btn = new Button {
                    Content = item.Content, HorizontalAlignment = HorizontalAlignment.Stretch, HorizontalContentAlignment = HorizontalAlignment.Left
                };
                btn.Click += OnClickHis;
                grid.Children.Add(btn);

                btn = new Button {
                    Content = "\uE009", Style = Res.字符按钮
                };
                btn.Click += OnDelHis;
                Grid.SetColumn(btn, 1);
                grid.Children.Add(btn);

                Items.Add(grid);
            }
        }
Пример #10
0
 void OnClearHis(object sender, RoutedEventArgs e)
 {
     using (Items.Defer())
     {
         RemoveAllHis();
     }
     AtState.Exec($"delete from SearchFvHis where BaseUri='{_baseUri}'");
 }
Пример #11
0
 /// <summary>
 /// 恢复默认布局
 /// 1. 删除状态库的历史布局
 /// 2. 加载最初布局
 /// </summary>
 public void LoadDefaultLayout()
 {
     if (AllowSaveLayout())
     {
         AtState.Exec($"delete from DockLayout where BaseUri=\"{_owner.BaseUri.AbsolutePath}\"");
     }
     ApplyLayout(_default);
     _owner.AllowResetLayout = false;
 }
Пример #12
0
 async void OnLocalDel(object sender, Mi e)
 {
     if (await Kit.Confirm("确认要删除码?"))
     {
         if (await AtState.Delete((ClientLog)_fv1.Data))
         {
             _fv1.Data = null;
         }
     }
 }
Пример #13
0
        static bool NeedRefresh()
        {
            // 超过10小时需要刷新
            bool   refresh = true;
            string val     = AtState.GetCookie(_refreshKey);

            if (!string.IsNullOrEmpty(val) && DateTime.TryParse(val, out var last))
            {
                refresh = (Kit.Now - last).TotalHours >= 10;
            }
            return(refresh);
        }
Пример #14
0
 async void OnLocalSave(object sender, Mi e)
 {
     if (await AtState.Save((ClientLog)_fv1.Data, false))
     {
         _fv1.AcceptChanges();
         Kit.Msg("本地库保存成功!");
     }
     else
     {
         Kit.Msg("本地库保存失败!");
     }
 }
Пример #15
0
        /// <summary>
        /// 接收服务器推送的聊天信息
        /// </summary>
        /// <param name="p_letter"></param>
        internal static async void ReceiveLetter(LetterInfo p_letter)
        {
            if (p_letter == null || string.IsNullOrEmpty(p_letter.ID))
            {
                return;
            }

            // 撤回消息
            if (p_letter.LetterType == LetterType.Undo)
            {
                var letter = AtState.First <Letter>("select * from Letter where MsgID=@msgid and LoginID=@loginid and IsReceived=1", new Dict {
                    { "msgid", p_letter.ID }, { "loginid", Kit.UserID }
                });
                if (letter != null)
                {
                    // 删除
                    AtState.Exec($"delete from Letter where ID={letter.ID}");
                    UndoLetter?.Invoke(letter);
                }
                return;
            }

            // 新消息
            Letter l = new Letter(
                LoginID: Kit.UserID,
                MsgID: p_letter.ID,
                OtherID: p_letter.SenderID,
                OtherName: p_letter.SenderName,
                LetterType: p_letter.LetterType,
                Content: p_letter.Content,
                STime: p_letter.SendTime,
                IsReceived: true,
                Unread: true);

            // 自增主键插入后自动赋值
            await AtState.Save(l, false);

            // 外部可修改 Unread 状态
            NewLetter?.Invoke(l);

            if (l.Unread)
            {
                // 外部未读提示
                StateChanged?.Invoke(l.OtherID);
                ShowUnreadNotify(l);
            }
            else
            {
                // Unread状态被修改
                await AtState.Save(l, false);
            }
        }
Пример #16
0
        void OnQueryLocal(object sender, Mi e)
        {
            Table tbl = AtState.Query("select * from ClientLog limit 1");

            if (tbl.Count > 0)
            {
                _fv1.Data = tbl[0];
            }
            else
            {
                Kit.Msg("本地库无数据!");
            }
        }
Пример #17
0
        /// <summary>
        /// 注销后重新登录
        /// </summary>
        public async void Logout()
        {
            // 先停止接收,再清空用户信息
            PushHandler.StopRecvPush();
            // 注销时清空用户信息
            Kit.ResetUser();

            AtState.DeleteCookie("LoginPhone");
            AtState.DeleteCookie("LoginPwd");

            await Kit.Stub.OnLogout();

            Startup.ShowLogin(false);
        }
Пример #18
0
        public FileListDemo()
        {
            InitializeComponent();
            var xml = AtState.GetCookie("FileTransDemo");

            if (!string.IsNullOrEmpty(xml))
            {
                _fl.Data = xml;
            }
            else
            {
                // Fsm中的测试文件
                _fl.Data = "[[\"photo/1.jpg\",\"1\",\"300 x 300 (.jpg)\",49179,\"daoting\",\"2020-03-13 10:37\"],[\"photo/Logon.wav\",\"Logon\",\"00:04\",384496,\"daoting\",\"2020-03-13 10:37\"],[\"photo/mov.mp4\",\"mov\",\"00:00:10 (320 x 176)\",788493,\"daoting\",\"2020-03-13 10:37\"],[\"photo/profilephoto.jpg\",\"profilephoto\",\"300 x 300 (.jpg)\",17891,\"daoting\",\"2020-03-13 10:37\"],[\"photo/文本文档.txt\",\"文本文档\",\"txt文件\",8,\"daoting\",\"2020-03-13 10:37\"],[\"photo/项目文档.docx\",\"项目文档\",\"docx文件\",13071,\"daoting\",\"2020-03-13 10:37\"],[\"photo/mov.mp4\",\"mov\",\"00:00:10 (320 x 176)\",788493,\"daoting\",\"2020-03-13 10:37\"]]";
            }
        }
Пример #19
0
        async void SaveCookie(string p_text)
        {
            _lastText = p_text;
            // 删除重复
            AtState.Exec($"delete from SearchFvHis where BaseUri='{_baseUri}' and Content='{p_text}'");

            SearchFvHis his = new SearchFvHis(BaseUri: _baseUri, Content: p_text);
            await AtState.Save(his, false);

            using (Items.Defer())
            {
                RemoveAllHis();
                LoadHisItems();
            }
        }
Пример #20
0
        /// <summary>
        /// 保存当前布局
        /// </summary>
        public void SaveCurrentLayout()
        {
            // 宽度小时不保存
            if (!AllowSaveLayout())
            {
                return;
            }

            Kit.RunAsync(() =>
            {
                DockLayout cookie = new DockLayout(_owner.BaseUri.AbsolutePath, WriteXml());
                AtState.Save(cookie, false);
                _owner.AllowResetLayout = true;
            });
        }
Пример #21
0
        /// <summary>
        /// Phone模式附加标题右键菜单
        /// </summary>
        /// <param name="p_elem">标题元素</param>
        /// <param name="p_win">所属窗口</param>
        public static void OnPhoneTitleTapped(FrameworkElement p_elem, Win p_win)
        {
            if (p_elem == null || p_win == null)
            {
                return;
            }

            p_elem.RightTapped += (s, e) =>
            {
                if (_menu == null)
                {
                    _menu = new Menu {
                        IsContextMenu = true, Placement = MenuPosition.BottomLeft
                    };
                    var item = new Mi {
                        ID = "取消自启动"
                    };
                    item.Click += (o, a) => Startup.DelAutoStart();
                    _menu.Items.Add(item);

                    item = new Mi {
                        ID = "设置自启动"
                    };
                    item.Click += SetAutoStart;
                    _menu.Items.Add(item);

                    item = new Mi {
                        ID = "系统监视"
                    };
                    item.Click += (o, a) => SysTrace.ShowBox();
                    _menu.Items.Add(item);
                }

                var autoStart = AtState.GetAutoStart();
                if (autoStart != null &&
                    autoStart.WinType == p_win.GetType().AssemblyQualifiedName &&
                    (p_win.Params == null || autoStart.Params == JsonSerializer.Serialize(p_win.Params, JsonOptions.UnsafeSerializer)))
                {
                    _menu.Items[0].Visibility = Visibility.Visible;
                    _menu.Items[1].Visibility = Visibility.Collapsed;
                }
                else
                {
                    _menu.Items[0].Visibility = Visibility.Collapsed;
                    _menu.Items[1].Visibility = Visibility.Visible;
                    _currentWin = p_win;
                }
                _ = _menu.OpenContextMenu(default, p_elem);
Пример #22
0
        public async Task ShowDlg(long p_fromUserID)
        {
            if (Kit.IsPhoneUI)
            {
                HideTitleBar = true;
            }
            else
            {
                IsPinned = true;
                SetSize(600, -60);
            }

            _other       = AtState.First <ChatMember>($"select * from ChatMember where id={p_fromUserID}");
            _tbInfo.Text = $"[{_other.Name}] 邀请您视频通话...";
            await ShowAsync();
        }
Пример #23
0
        void OnDelHis(object sender, RoutedEventArgs e)
        {
            SearchFvHis his = (SearchFvHis)((Button)sender).DataContext;

            if (AtState.Exec($"delete from SearchFvHis where BaseUri='{_baseUri}' and Content='{his.Content}'") == 1)
            {
                for (int i = _hisStart; i < Items.Count; i++)
                {
                    if (((Button)sender).DataContext == Items[i].DataContext)
                    {
                        Items.RemoveAt(i);
                        break;
                    }
                }
            }
        }
Пример #24
0
        async void OnReset(object sender, Mi e)
        {
            int cntFixed = Kit.Stub.FixedMenus == null ? 0 : Kit.Stub.FixedMenus.Count;

            if (MenuKit.FavMenus.Count > cntFixed)
            {
                var cnt = AtState.Exec($"delete from menufav where userid={Kit.UserID}");
                if (cnt > 0)
                {
                    await MenuKit.LoadMenus();

                    _lv.Data     = MenuKit.RootPageMenus;
                    e.Visibility = Visibility.Collapsed;
                    Kit.Msg("重置常用菜单成功!");
                }
            }
        }
Пример #25
0
        /// <summary>
        /// 清除和某人的未读消息状态
        /// </summary>
        /// <param name="p_otherid">对方标识</param>
        public static void ClearUnreadFlag(long p_otherid)
        {
            Kit.RunAsync(() =>
            {
                int cnt = AtState.Exec("update Letter set unread=0 where otherid=@otherid and loginid=@loginid and unread=1",
                                       new Dict
                {
                    { "otherid", p_otherid },
                    { "loginid", Kit.UserID }
                });

                if (cnt > 0)
                {
                    StateChanged?.Invoke(p_otherid);
                }
            });
        }
Пример #26
0
        /// <summary>
        /// 按默认流程启动:
        /// 1. 更新打开模型库
        /// 2. 已登录过,先自动登录
        /// 3. 未登录或登录失败时,根据 p_loginFirst 显示登录页或主页
        /// </summary>
        /// <param name="p_loginFirst">是否强制先登录</param>
        /// <returns></returns>
        public static async Task Run(bool p_loginFirst)
        {
            // 更新打开模型库
            if (!await OpenModelDb())
            {
                return;
            }

            string phone = AtState.GetCookie("LoginPhone");
            string pwd   = AtState.GetCookie("LoginPwd");

            if (!string.IsNullOrEmpty(phone) && !string.IsNullOrEmpty(pwd))
            {
                // 自动登录
                var result = await new UnaryRpc(
                    _svcName,
                    "Entry.LoginByPwd",
                    phone,
                    pwd
                    ).Call <LoginResult>();

                // 登录成功
                if (result.IsSuc)
                {
                    Kit.InitUser(result);
                    // 切换到主页
                    ShowHome();
                    // 接收服务器推送
                    PushHandler.Register();
                    return;
                }
            }

            // 未登录或登录失败
            if (p_loginFirst)
            {
                // 强制先登录
                ShowLogin(false);
            }
            else
            {
                // 未登录先显示主页
                ShowHome();
            }
        }
Пример #27
0
        /// <summary>
        /// 打开菜单项窗口,可以由点击菜单项或直接代码构造Menu的方式调用
        /// </summary>
        /// <param name="p_menu">OmMenu实例</param>
        /// <returns>返回打开的窗口或视图,null表示打开失败</returns>
        public static object OpenMenu(OmMenu p_menu)
        {
            if (p_menu == null)
            {
                Kit.Msg("打开菜单项不可为空!");
                return(null);
            }

            Type tp = Kit.GetViewType(p_menu.ViewName);

            if (tp == null)
            {
                Kit.Msg(string.Format("打开菜单时未找到视图【{0}】!", p_menu.ViewName));
                return(null);
            }

            Icons icon;

            Enum.TryParse(p_menu.Icon, out icon);
            object win = Kit.OpenWin(tp, p_menu.Name, icon, string.IsNullOrEmpty(p_menu.Params) ? null : p_menu.Params);

            // 保存点击次数,用于确定哪些是收藏菜单
            if (win != null)
            {
                Task.Run(() =>
                {
                    if (AtModel.GetScalar <int>($"select count(id) from ommenu where id=\"{p_menu.ID}\"") > 0)
                    {
                        // 点击次数保存在客户端
                        Dict dt      = new Dict();
                        dt["userid"] = Kit.UserID;
                        dt["menuid"] = p_menu.ID;
                        int cnt      = AtState.Exec("update menufav set clicks=clicks+1 where userid=:userid and menuid=:menuid", dt);
                        if (cnt == 0)
                        {
                            AtState.Exec("insert into menufav (userid, menuid, clicks) values (:userid, :menuid, 1)", dt);
                        }
                    }
                    // 收集使用频率
                    //await AtAuth.ClickMenu(p_menu.ID);
                });
            }
            return(win);
        }
Пример #28
0
        //**************************************************************************
        // 响应式设计:三种布局方式对应三种界面宽度
        // 1. 界面宽度 <= 640px,PhoneUI模式,4"到6"设备 或 缩小的窗口,只一列面板
        // 2. 界面宽度在 641px ~ 1007px,7"到12"设备 或 缩小的窗口,最多两列面板
        // 3. 界面宽度 >= 1008px,13"及更大设备,最多三列面板
        //**************************************************************************

        /// <summary>
        /// Win宽度变化时自动调整
        /// </summary>
        /// <param name="p_width"></param>
        public void OnWidthChanged(double p_width)
        {
            double width = 0;
            int    index = -1;

            for (int i = 0; i < _colsWidth.Count; i++)
            {
                width += _colsWidth[i];
                if (width > p_width)
                {
                    index = i;
                    break;
                }
            }
            if (_fitCols == index)
            {
                return;
            }

            _fitCols = index;
            if (_fitCols == -1)
            {
                // 宽度足够,加载历史布局或默认布局
                DockLayout cookie;
                if (AllowSaveLayout() &&
                    (cookie = AtState.First <DockLayout>($"select * from DockLayout where BaseUri=\"{_owner.BaseUri.AbsolutePath}\"")) != null &&
                    ApplyLayout(cookie.Layout))
                {
                    _owner.AllowResetLayout = true;
                }
                else
                {
                    ApplyLayout(_default);
                    _owner.AllowResetLayout = false;
                }
            }
            else
            {
                // 自动隐藏两侧
                ApplyAutoHide();
                _owner.AllowResetLayout = false;
            }
        }
Пример #29
0
        /// <summary>
        /// 撤回发出的消息
        /// </summary>
        /// <param name="p_letter">待撤消息</param>
        /// <returns></returns>
        public static async Task <bool> SendUndoLetter(Letter p_letter)
        {
            if (p_letter == null)
            {
                return(false);
            }

            LetterInfo li = new LetterInfo
            {
                ID         = p_letter.MsgID,
                SenderID   = Kit.UserID,
                SenderName = Kit.UserName,
                LetterType = LetterType.Undo,
                SendTime   = Kit.Now
            };
            await AtMsg.SendLetter(p_letter.OtherID, li);

            AtState.Exec($"delete from Letter where ID={p_letter.ID}");
            return(true);
        }
Пример #30
0
        /// <summary>
        /// 发送聊天信息
        /// </summary>
        /// <param name="p_recvID"></param>
        /// <param name="p_recvName"></param>
        /// <param name="p_content"></param>
        /// <param name="p_type"></param>
        /// <returns></returns>
        public static async Task <Letter> SendLetter(
            long p_recvID,
            string p_recvName,
            string p_content,
            LetterType p_type)
        {
            Throw.IfNullOrEmpty(p_content);

            LetterInfo li = new LetterInfo
            {
                ID         = Kit.NewGuid,
                SenderID   = Kit.UserID,
                SenderName = Kit.UserName,
                LetterType = p_type,
                Content    = p_content,
                SendTime   = Kit.Now
            };
            bool isOnline = await AtMsg.SendLetter(p_recvID, li);

            // 本地记录
            Letter l = new Letter(
                LoginID: Kit.UserID,
                MsgID: li.ID,
                OtherID: p_recvID,
                OtherName: p_recvName,
                OtherIsOnline: isOnline,
                IsReceived: false,
                Unread: false,
                LetterType: p_type,
                Content: p_content,
                STime: li.SendTime);

            // 自增主键插入后自动赋值
            await AtState.Save(l, false);

            NewLetter?.Invoke(l);
            return(l);
        }