PureMVC和Unity3D的UGUI制作一个简单的员工管理系统实例

来源:互联网 发布:河铉雨 知乎 编辑:程序博客网 时间:2024/06/10 21:25
转载至  简书http://www.jianshu.com/p/904b36ad37e2


运行实例演示.png

前言:

1.关于PureMVC:

MVC框架在很多项目当中拥有广泛的应用,很多时候做项目前人开坑开了一半就消失了,后人为了填补各种的坑就遭殃的不得了。嘛,程序猿大家都不喜欢像文案策划一样组织文字写东西,也不喜欢看别人留下不清不楚的文档,还不如看代码来得实在。刚开始新人看代码是看得头晕,因为这样那样的东西不一定能完全猜得透。而老人家就算有经验和阅历,也没有这么多的体力去看一个庞大而又复杂的糟糕项目。因为这种需求,Unity3D的程序猿就统一组织起来,想做一个完整规范的程序框架,而这时,PureMVC就诞生了。我个人喜欢PureMVC的原因也很简单,因为它简单粗暴,和Unity3D之间没有依赖性,加上又开源,真的遇到Bug能拿到源代码来调试也是很容易执行的。Unity3D应用商店还有一个同类产品叫uFrame Game Framework,它对Unity版本有着依赖,拖视图虽然方便,但是一旦出bug真的改得够呛的,所以不推荐使用它。下文便是使用PureMVC和Unity3D的UGUI制作一个简单的员工管理系统实例。

2.通过MVC模式在Unity项目当中应用的特别提醒:

(1)Unity3D是基于组件设计的,如果没有好的规划,组件之间会产生复杂的调用关系,导致组件之间复杂的依赖,从而破坏了整个系统结构,因此需要设计时确定组件的层次关系,确保依赖关系只存在于下层对上层。而这个是业务逻辑设计问题,PureMVC帮不了你。
(2)仅仅用上MVC,解决不了什么问题,或许解决了1%,剩下的99%就被挪到了MVC的C里,当你庆祝MVC竣工时,99%的问题在那里默默的微笑的看着你。(话说以前写PHP的CI框架时候,一堆东西扔到XxxAction.Class.php里面,发现和摆的乱七八糟的架构没区别,只是大家都习惯了这套框架的规矩,看代码找某个东西稍微好找而已,本质上还是考验基本功和对项目的熟悉程度的,23333)

3.PureMVC通过4种pattern实现隔离变化:

(1)facade非常适合将UI界面对游戏数据的依赖解耦,将UI操作数据的请求封装在facade 接口里面,同时数据变化对UI的影响可以通过notification事件通知来实现,该模式应用得非常常见。
(2)command模式统一对对象的操作,将键盘输入,网络输入输出统一成command来操控游戏对象。
(3)proxy维护数据,提供某块数据统一的初始化,访问和修改接口。
(4)mediator没怎么用过,我们的游戏中的UI界面每次变化一般都是整体更新的,不常用局部更新。
以上4中pattern请务必牢牢记住,请务必牢牢记住,请务必牢牢记住。重要的事情要说3便。

4.PureMVC的流程示意图

(1)在puremvc中,model/view/controller统一是由Facade类的单件实例来统筹管理的。
(2)PureMVC的基本流程:启动PureMVC—>建立Mediator来操作视觉元素(按钮与文本框)—>点击按钮发送Notification->文本框接收Notification改变内容。
(3)大致流程可理解为:通过Facade类的单件实例(即:统一的门面) 启动 puremvc环境,启动同时注册Command对象(相当于asp.net mvc中的controller),然后Command通过与之关联的facade(即前面的单件实例)来注册Mediator(中介者:用于把View与Command联系起来)。
(4)当UI界面(即View)上有动静时(比如按钮点击了之类),与之关联的Mediator(中介者)会发送通知给facade,然后facade会调用command对象执行相关的处理。(即:消息响应)


PureMVC示意图.png

一.引入PureMVC的插件

1.下载PureMVC

请访问地址
https://github.com/PureMVC/puremvc-csharp-standard-framework/wiki

安装

2.把PureMVC.DotNET.35.dll放到Plugins里面就好了。

QA

3.这里有一个很简单的基本案例可以参考一下
http://www.open-open.com/lib/view/open1452657515480.html

二.动手配置文件

1.需要完成的实例如下:


实现的界面效果.png

2.具体实现的目标:

(1)在Scripts文件夹下,分别设置模型、视图、控制器对应的文件夹Model、View、Controller,分别放置处理数据模型的脚本、处理显示视图的脚本、处理逻辑控制的脚本。
(2)如界面,一个Unity3D和UGUI制作的简单员工管理系统,Employee Admin,其中员工界面Users显示有哪些员工在登记范围内,而New和Delete分别是添加和删除某个员工的信息。然后下面的员工信息界面User Profile则是对员工信息的一个具体编辑和修正。

三.主要实现步骤

1.启动文件AppFacade.cs 作为PureMVC框架的入口文件。

using UnityEngine;using System.Collections;using PureMVC.Patterns;using PureMVC.Interfaces;//Facade模式的单例public class ApplicationFacade : Facade{    //实例化函数,保证单例模式(Singleton)运行该函数    public new static IFacade Instance    {        get        {            if(m_instance == null)            {                lock(m_staticSyncRoot)                {                    if (m_instance == null)                    {                        Debug.Log("ApplicationFacade");                        m_instance = new ApplicationFacade();                    }                }            }            return m_instance;        }    }    //启动PureMVC的入口函数    public void Startup(MainUI mainUI)    {        Debug.Log("Startup() to SendNotification.");        SendNotification(EventsEnum.STARTUP, mainUI);    }    //该类的构造器    protected ApplicationFacade()    {    }    //设置静态    static ApplicationFacade()    {    }    //初始化控制器函数    protected override void InitializeController()    {        Debug.Log("InitializeController()");        base.InitializeController();        RegisterCommand(EventsEnum.STARTUP, typeof(StartupCommand));        RegisterCommand(EventsEnum.DELETE_USER, typeof(DeleteUserCommand));    }}

2.对PureMVC需要处理的事件用EventsEnum.cs存放

using UnityEngine;using System.Collections;//处理事件的枚举public class EventsEnum{    public const string STARTUP = "startup";//启动事件    public const string NEW_USER = "newUser";//新建用户    public const string DELETE_USER = "deleteUser";//删除用户    public const string CANCEL_SELECTED = "cancelSelected";//取消选择    public const string USER_SELECTED = "userSelected";//选择用户    public const string USER_ADDED = "userAdded";//添加用户    public const string USER_UPDATED = "userUpdated";//更新用户    public const string USER_DELETED = "userDeleted";//删除用户    public const string ADD_ROLE = "addRole";//添加角色    public const string ADD_ROLE_RESULT = "addRoleResult";//查询添加角色的结果}

3.然后在Unity的场景中创建一个MainUI.cs文件,挂在需要启动PureMVC的组件上。就可以启动了。

using UnityEngine;using System.Collections;//处理该UI场景的入口public class MainUI : MonoBehaviour{    public UserList userList;    public UserForm userForm;    //启动函数    void Awake()    {        //启动PureMVC程序,执行StartUP()方法        ApplicationFacade facade = ApplicationFacade.Instance as ApplicationFacade;        facade.Startup(this);    }}

4.对Controller部分进行处理

然后我们对执行逻辑的处理事件进行补充。新建一个文件夹Controller,暂时先放置StartupCommand.cs和DeleteUserCommand.cs。处理上述所说的逻辑事件
首先,处理启动事件

using UnityEngine;using System.Collections;using PureMVC.Patterns;using PureMVC.Interfaces;//启动事件public class StartupCommand : SimpleCommand, ICommand{    //复写原有的Execute执行函数    public override void Execute(INotification notification)    {        //注册统一的数据接口UserProxy,给其他事件处理        Debug.Log("StartupCommand.Execute()");        Facade.RegisterProxy(new UserProxy());        //注册局部界面Mediator,给其他事件处理        MainUI mainUI = notification.Body as MainUI;        Facade.RegisterMediator(new UserListMediator(mainUI.userList));        Facade.RegisterMediator(new UserFormMediator(mainUI.userForm));    }}

其次,处理删除用户事件

using PureMVC.Patterns;using PureMVC.Interfaces;//删除用户事件public class DeleteUserCommand : SimpleCommand, ICommand{   //复写原有的Execute执行函数    public override void Execute(INotification notification)    {        //获取要删除的对象user        UserVO user = (UserVO)notification.Body;        //获取处理数据操作的userProxy        UserProxy userProxy = (UserProxy)Facade.RetrieveProxy(UserProxy.NAME);        //操作数据,删除user        userProxy.DeleteItem(user);        //删除完毕,广播USER_DELETED进行通知        SendNotification(EventsEnum.USER_DELETED);    }}

5.对Model部分进行处理

然后是对Model模型数据的定义哈,首先要记录的信息用UserVO来表示

using UnityEngine;using System.Collections;//显示用的数据信息UserViewObjectpublic class UserVO{    //用户名    public string UserName    {        get { return m_userName; }    }    private string m_userName = "";    //名字    public string FirstName    {        get { return m_firstName; }    }    private string m_firstName = "";    //姓氏    public string LastName    {        get { return m_lastName; }    }    private string m_lastName = "";    //邮箱    public string Email    {        get { return m_email; }    }    private string m_email = "";    //密码    public string Password    {        get { return m_password; }    }    private string m_password = "";    //部门    public string Department    {        get { return m_department; }    }    private string m_department = "";    //是否合法    public bool IsValid    {        get        {            return !string.IsNullOrEmpty(UserName) && !string.IsNullOrEmpty(Password);        }    }    //合并名字    public string GivenName    {        get { return LastName + ", " + FirstName; }    }    //构造器    public UserVO()    {    }    //构造函数    public UserVO(string uname, string fname, string lname, string email, string password, string department)    {        if (uname != null) m_userName = uname;        if (fname != null) m_firstName = fname;        if (lname != null) m_lastName = lname;        if (email != null) m_email = email;        if (password != null) m_password = password;        if (department != null) m_department = department;    }}

接着对操作数据的UserProxy进行补充

using UnityEngine;using System.Collections.Generic;using PureMVC.Patterns;using PureMVC.Interfaces;//数据操作public class UserProxy : Proxy, IProxy{    public new const string NAME = "UserProxy";    //返回数据操作类    public IList<UserVO> Users    {        get { return (IList<UserVO>) base.Data; }    }    //构造函数,添加几条数据进去先    public UserProxy():base(NAME, new List<UserVO>())    {        Debug.Log("UserProxy()");        //添加几条测试用的数据                AddItem(new UserVO("lstooge", "Larry", "Stooge", "larry@stooges.com", "ijk456", "ACCT"));        AddItem(new UserVO("cstooge", "Curly", "Stooge", "curly@stooges.com", "xyz987", "SALES"));        AddItem(new UserVO("mstooge", "Moe", "Stooge", "moe@stooges.com", "abc123", "PLANT"));        AddItem(new UserVO("lzh", "abc", "def", "lzh@stooges.com", "abc123", "IT"));    }    //添加数据的方法    public void AddItem(UserVO user)    {        Users.Add(user);    }    //更新数据的方法    public void UpdateItem(UserVO user)    {        for (int i = 0; i < Users.Count; i++)        {            if (Users[i].UserName.Equals(user.UserName))            {                Users[i] = user;                break;            }        }    }    //删除数据的方法    public void DeleteItem(UserVO user)    {        for (int i = 0; i < Users.Count; i++)        {            if (Users[i].UserName.Equals(user.UserName))            {                Users.RemoveAt(i);                break;            }        }    }}

6.接下来对VIew部分进行实现

显示用户界面列表的UserList和填写用户具体信息的UserForm
列表单条数据部分

using UnityEngine;using UnityEngine.UI;using System.Collections;//UserList列表当中单条数据信息public class UserList_Item : MonoBehaviour{    //定义UI组件    public Text txt_userName;//用户名文本框    public Text txt_firstName;//名字文本框    public Text txt_lastName;//姓氏文本框    public Text txt_email;//邮件文本框    public Text txt_department;//部门文本框    //定义User信息类    public UserVO userData;    //更新User类    public void UpdateData(UserVO data)    {        //获取需要更改的User信息        this.userData = data;        //更改UI的文字信息        txt_userName.text = data.UserName;        txt_firstName.text = data.FirstName;        txt_lastName.text = data.LastName;        txt_email.text = data.Email;        txt_department.text = data.Department;    }}

用户列表部分

using UnityEngine;using UnityEngine.UI;using System.Collections;using System.Collections.Generic;//UserList用户界面列表部分public class UserList : MonoBehaviour{    //定义UI组件    public Text txt_userCount;//用户列表文本框    public UGUI_MyToggleGroup myToggleGroup;//用户列表滑动条    public Button btn_New;//新建按钮    public Button btn_Delete;//删除按钮    public UserList_Item itemPrefab;//单个列表文件的预置体    List<UserList_Item> itemList = new List<UserList_Item>();//临时存列表    //定义事件操作    public System.Action NewUser;//添加用户事件    public System.Action DeleteUser;//删除用户事件    public System.Action SelectUser;//选择用户事件    //定义数据    public UserVO SelectedUserData;//列表中选择好的用户    private IList<UserVO> m_currentUsers;//当前选择的用户    //开始函数    void Start ()    {        itemPrefab.gameObject.SetActive(false);        myToggleGroup.onToggleChange.AddListener(onSelectUserItem);        btn_New.onClick.AddListener(onClick_btn_New);        btn_Delete.onClick.AddListener(onClick_btn_Delete);        UpdateButtons();    }    //加载用户    public void LoadUsers(IList<UserVO> list)    {        m_currentUsers = list;        RefreshUI(list);    }    //点击新建    void onClick_btn_New()    {        if (NewUser != null) NewUser();    }    //点击删除    void onClick_btn_Delete()    {        if (DeleteUser != null) DeleteUser();    }    //选择物体    void onSelectUserItem(Toggle itemToggle)    {        if (itemToggle == null)        {            return;        }        UserList_Item item = itemToggle.GetComponent<UserList_Item>();        this.SelectedUserData = item.userData;        UpdateButtons();        if (SelectUser != null) SelectUser();    }    //取消选择    public void Deselect()    {        myToggleGroup.toggleGroup.SetAllTogglesOff();        this.SelectedUserData = null;        UpdateButtons();    }    //刷新UI    void RefreshUI(IList<UserVO> datas)    {        ClearItems();        foreach (var data in datas)        {            UserList_Item item = CreateItem();            item.UpdateData(data);            itemList.Add(item);        }        txt_userCount.text = datas.Count.ToString();    }    //新建列表项目    UserList_Item CreateItem()    {        UserList_Item item = GameObject.Instantiate<UserList_Item>(itemPrefab);        item.transform.SetParent(itemPrefab.transform.parent);        item.gameObject.SetActive(true);        item.transform.localScale = Vector3.one;        item.transform.localPosition = Vector3.zero;        return item;    }    //清空列表    void ClearItems()    {        foreach(var item in itemList)        {            Destroy(item.gameObject);        }        itemList.Clear();    }    //更新按钮    private void UpdateButtons()    {        btn_Delete.interactable = (SelectedUserData != null);    }}

用户个人信息部分

using UnityEngine;using UnityEngine.UI;using System.Collections;using UnityEngine.EventSystems;//用户个人信息表单模式?编辑:新增public enum UserFormMode{    ADD,    EDIT,}//用户个人信息表单public class UserForm : MonoBehaviour{    //UI项的定义    public InputField txt_firstName;    public InputField txt_lastName;    public InputField txt_email;    public InputField txt_userName;    public InputField txt_password;    public InputField txt_confirmPassword;    public InputField txt_department;    public Button btn_updateUser;    public Button btn_cancel;    //其他    public System.Action AddUser;    public System.Action UpdateUser;    public System.Action CancelUser;    //用户信息获取    public UserVO User    {        get { return m_user; }    }    private UserVO m_user;    //用户信息表单    public UserFormMode Mode    {        get { return m_mode; }    }    private UserFormMode m_mode = UserFormMode.ADD;    //开始    void Start ()    {        //设置UI        btn_updateUser.onClick.AddListener(btn_updateUser_Click);        btn_cancel.onClick.AddListener(btn_cancel_Click);        txt_userName.onValueChange.AddListener(InputField_onValueChange);        txt_password.onValueChange.AddListener(InputField_onValueChange);        txt_confirmPassword.onValueChange.AddListener(InputField_onValueChange);        UpdateButtons();    }    //显示当前用户信息    public void ShowUser(UserVO user, UserFormMode mode)    {        m_mode = mode;        if (user == null)        {            ClearForm();        }        else        {            m_user = user;            txt_firstName.text = user.FirstName;            txt_lastName.text = user.LastName;            txt_email.text = user.Email;            txt_userName.text = user.UserName;            txt_password.text = txt_confirmPassword.text = user != null ? user.Password : "";            txt_department.text = user.Department;            //txt_firstName.ActivateInputField();            EventSystem.current.SetSelectedGameObject(txt_firstName.gameObject);            //txt_firstName.MoveTextEnd(false);            txt_firstName.caretPosition = txt_firstName.text.Length - 1;            UpdateButtons();        }    }    //更新按钮    private void UpdateButtons()    {        if (btn_updateUser != null)        {            btn_updateUser.interactable = (txt_firstName.text.Length > 0 && txt_password.text.Length > 0 && txt_password.text.Equals(txt_confirmPassword.text));        }    }    //清空表单    public void ClearForm()    {        m_user = null;        txt_firstName.text = txt_lastName.text = txt_email.text = txt_userName.text = "";        txt_password.text = txt_confirmPassword.text = "";        txt_department.text = "";        UpdateButtons();    }    //更新用户信息    void btn_updateUser_Click()    {        m_user = new UserVO(            txt_userName.text, txt_firstName.text,             txt_lastName.text, txt_email.text,             txt_password.text, txt_department.text);        if (m_user.IsValid)        {            if (m_mode == UserFormMode.ADD)            {                if (AddUser != null) AddUser();            }            else            {                if (UpdateUser != null) UpdateUser();            }        }    }    //取消信息    void btn_cancel_Click()    {        if (CancelUser != null) CancelUser();    }    //输入    void InputField_onValueChange(string value)    {        UpdateButtons();    }}

最后,对局部更新UI的行为进行完善Mediator

using UnityEngine;using System.Collections;using PureMVC.Patterns;using PureMVC.Interfaces;using System.Collections.Generic;//更新UserList部分public class UserListMediator : Mediator, IMediator{    private UserProxy userProxy;    public new const string NAME = "UserListMediator";    private UserList View    {        get { return (UserList)ViewComponent; }    }    public UserListMediator(UserList userList)            : base(NAME, userList)    {        Debug.Log("UserListMediator()");        userList.NewUser += userList_NewUser;        userList.DeleteUser += userList_DeleteUser;        userList.SelectUser += userList_SelectUser;    }    public override void OnRegister()    {        Debug.Log("UserListMediator.OnRegister()");        base.OnRegister();        userProxy = Facade.RetrieveProxy(UserProxy.NAME) as UserProxy;        View.LoadUsers(userProxy.Users);    }    void userList_NewUser()    {        UserVO user = new UserVO();        SendNotification(EventsEnum.NEW_USER, user);    }    void userList_DeleteUser()    {        SendNotification(EventsEnum.DELETE_USER, View.SelectedUserData);    }    void userList_SelectUser()    {        SendNotification(EventsEnum.USER_SELECTED, View.SelectedUserData);    }    public override IList<string> ListNotificationInterests()    {        IList<string> list = new List<string>();        list.Add(EventsEnum.USER_DELETED);        list.Add(EventsEnum.CANCEL_SELECTED);        list.Add(EventsEnum.USER_ADDED);        list.Add(EventsEnum.USER_UPDATED);        return list;    }    public override void HandleNotification(INotification notification)    {        switch(notification.Name)        {            case EventsEnum.USER_DELETED:                View.Deselect();                View.LoadUsers(userProxy.Users);                break;            case EventsEnum.CANCEL_SELECTED:                View.Deselect();                break;            case EventsEnum.USER_ADDED:                View.Deselect();                View.LoadUsers(userProxy.Users);                break;            case EventsEnum.USER_UPDATED:                View.Deselect();                View.LoadUsers(userProxy.Users);                break;        }    }}
using UnityEngine;using System.Collections;using PureMVC.Patterns;using PureMVC.Interfaces;using System.Collections.Generic;//更新UserForm部分public class UserFormMediator : Mediator, IMediator{    private UserProxy userProxy;    public new const string NAME = "UserFormMediator";    private UserForm View    {        get { return (UserForm)ViewComponent; }    }    public UserFormMediator(UserForm viewComponent)        : base(NAME, viewComponent)    {        Debug.Log("UserFormMediator()");        View.AddUser += UserForm_AddUser;        View.UpdateUser += UserForm_UpdateUser;        View.CancelUser += UserForm_CancelUser;    }    public override void OnRegister()    {        base.OnRegister();        userProxy = Facade.RetrieveProxy(UserProxy.NAME) as UserProxy;    }    void UserForm_AddUser()    {        UserVO user = View.User;        userProxy.AddItem(user);        SendNotification(EventsEnum.USER_ADDED, user);        View.ClearForm();    }    void UserForm_UpdateUser()    {        UserVO user = View.User;        userProxy.UpdateItem(user);        SendNotification(EventsEnum.USER_UPDATED, user);        View.ClearForm();    }    void UserForm_CancelUser()    {        SendNotification(EventsEnum.CANCEL_SELECTED);        View.ClearForm();    }    public override IList<string> ListNotificationInterests()    {        IList<string> list = new List<string>();        list.Add(EventsEnum.NEW_USER);        list.Add(EventsEnum.USER_DELETED);        list.Add(EventsEnum.USER_SELECTED);        return list;    }    public override void HandleNotification(INotification note)    {        UserVO user;        switch (note.Name)        {            case EventsEnum.NEW_USER:                user = (UserVO)note.Body;                View.ShowUser(user, UserFormMode.ADD);                break;            case EventsEnum.USER_DELETED:                View.ClearForm();                break;            case EventsEnum.USER_SELECTED:                user = (UserVO)note.Body;                View.ShowUser(user, UserFormMode.EDIT);                break;        }    }}

补充,UI的选择部分

using UnityEngine;using UnityEngine.UI;using System.Collections;[RequireComponent(typeof(Toggle))]public class UGUI_MyToggle : MonoBehaviour{        [SerializeField]Toggle toggle;    [SerializeField]UGUI_MyToggleGroup myToggleGroup;    void Start()    {        if (toggle == null) toggle = this.GetComponent<Toggle>();        if (myToggleGroup == null) myToggleGroup = toggle.group.GetComponent<UGUI_MyToggleGroup>();        toggle.onValueChanged.AddListener(onToggle);    }    void onToggle(bool value)    {        if(value)        {            myToggleGroup.ChangeToggle(toggle);        }    }}

//[lzh]
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Events;
using System.Collections;

public class ToggleEvent : UnityEvent<Toggle> { }

[RequireComponent(typeof(ToggleGroup))]
public class UGUI_MyToggleGroup : MonoBehaviour
{
public ToggleGroup toggleGroup;
public ToggleEvent onToggleChange = new ToggleEvent();

void Start(){    if (toggleGroup == null) toggleGroup = this.GetComponent<ToggleGroup>();}public void ChangeToggle(Toggle toggle){    onToggleChange.Invoke(toggle);}

}



作者:小小酥XX
链接:http://www.jianshu.com/p/904b36ad37e2
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 冷车启动水温报警灯亮了怎么办 租铺位面积比合同面积小怎么办 农村村民建房领居不肯签名怎么办 车祸死者家属不来协商赔偿怎么办 26岁想回去当老师了怎么办 面包车排量小空调带不凉快怎么办 科三包过不给退钱人跑了怎么办 护师职称考试成绩单丢了怎么办 河南二级建造师报名地址填错怎么办 山东以前的企业没有消防备案怎么办 重庆渝北初级审核时间过了怎么办 初级职称复核毕业证弄丢了怎么办 杭州公租房选房后变更单位的怎么办 契税交了贷款办不下来怎么办 天津公租房住满5年后怎么办 大江里钓鱼水流太急立不住漂怎么办 房子定金交了不想要了怎么办 房子付了首付不想要了怎么办 三国大时代4王越死了任务怎么办 红米2卡顿反应慢怎么办 国税和地税合并新进的公务员怎么办 买车合格证不给我们要怎么办 初级会计报名信息表填写错误怎么办 跨国快递需要收件人自行清关怎么办 腋下有异味怎么办邀约成都真愛 腋下有异味怎么办犀利成都真愛 腋下有异味怎么办有信成都真愛 成都车牌网上选号次数用完了怎么办 在志愿服务中遇到突发状况怎么办 商铺没有房产证不能办理消防怎么办 亳州办事大厅登录密码忘记了怎么办 户口已迁出结婚证丢了怎么办 户口已迁出多年结婚证丢了怎么办 芜湖长信正式工没转正怎么办辞职 买到9个月库存车怎么办 买到5个月库存车怎么办 把4s店新车撞了怎么办 网址导航已取消打不开网页是怎么办 如果邦华手机充电口有杂物怎么办? 当发生灾害或突发事故时怎么办 物流信息和和收货地址不一样怎么办