如何使用USER.DB找回丢失QQ中的好友?

本文介绍了一种通过复制旧QQ账号的user.db文件到新账号的方法来找回已丢失的QQ好友。具体步骤包括:找到旧账号文件夹内的user.db文件,将其复制到新账号文件夹内,登录新账号后将好友从“离线”状态移至“陌生人”,最后重新添加为好友。
想要找回已经丢失的QQ里的好友要注意以下几点哦~

1.你的QQ确实是丢了
2.你的QQ安装目录还没有删除
3.最重要的一点就是你已经申请了新的QQ号码

下面来详细介绍一下:
在你的QQ安装目录里会找到一个文件夹,名字是你已经丢失的QQ号码,打开它并找到一个名字是user.db的文件,找到后复制.
因为你已经重新申请成功了新的QQ号码,先退出你的新QQ号码,打开QQ安装目录,找到你新QQ的文件夹,然后把你复制的user.db文件粘贴到你的新号码文件夹里,
然后再登陆你的新QQ号码,你会发现里面你的好友都有了,但是状态都是“离线”,然后将他们全都选中拖到“陌生人”里.
再将你在“陌生人”里的好友再次全选中并拖到“我的好友”里面,最后将你原来的好友再重新加上就Ok拉~!
 
package com.example.kucun2.data; import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import androidx.annotation.NonNull; import androidx.room.Database; import androidx.room.Room; import androidx.room.RoomDatabase; import androidx.room.migration.Migration; import androidx.sqlite.db.SupportSQLiteDatabase; import com.example.kucun2.entity.User; import java.io.File; @Database(entities = {User.class}, version = 2, exportSchema = false ) public abstract class AppDatabase extends RoomDatabase { public abstract UserDao userDao(); private static volatile AppDatabase INSTANCE; public static AppDatabase getDatabase(Context context) { return Room.databaseBuilder(context, AppDatabase.class, "users.db") .addMigrations(MIGRATION_1_2) .addCallback(new RoomDatabase.Callback() { @Override public void onOpen(@NonNull SupportSQLiteDatabase db) { // 确保视图存在 db.execSQL("CREATE VIEW IF NOT EXISTS user_summary AS SELECT id, name FROM users"); } }) .fallbackToDestructiveMigrationOnDowngrade() .build(); } private static void migrateFromLegacy(Context context) { // 旧数据库迁移逻辑 SQLiteDatabase legacyDb = SQLiteDatabase.openDatabase( context.getDatabasePath("users.db").getPath(), null, SQLiteDatabase.OPEN_READONLY); Cursor cursor = legacyDb.rawQuery("SELECT * FROM users", null); // 数据迁移到Room数据库 UserDao dao = INSTANCE.userDao(); // 使用事务保证迁移完整性 INSTANCE.runInTransaction(() -> { while (cursor.moveToNext()) { User user = new User(cursor.getInt(0), cursor.getString(1), cursor.getString(2), cursor.getString(3), cursor.getInt(4) ); dao.insert(user); } cursor.close(); legacyDb.close(); }); } private static final Migration MIGRATION_1_2 = new Migration(1, 2) { @Override public void migrate(@NonNull SupportSQLiteDatabase db) { // 示例:添加新字段 // 示例:创建视图(不修改表结构) db.execSQL("CREATE TABLE users_temp (id INTEGER PRIMARY KEY, " + "name TEXT, " + "andy TEXT, " + "pass TEXT, " + "role INTEGER)" + ""); // 3. 迁移数据 db.execSQL("INSERT INTO users_temp (id, name, andy, pass, role) " + "SELECT id, name, andy, pass, role FROM users"); // 4. 删除旧表并重命名 db.execSQL("DROP TABLE users"); db.execSQL("ALTER TABLE users_temp RENAME TO users"); // 5. 维护视图 db.execSQL("DROP VIEW IF EXISTS user_summary"); db.execSQL("CREATE VIEW user_summary AS SELECT id, name FROM users"); } }; public static void deleteDatabase(Context context) { // 1. 关闭现有连接 if (INSTANCE != null) { INSTANCE.close(); INSTANCE = null; } // 2. 删除物理文件 context.deleteDatabase("users.db"); // 3. 清理残留文件(WAL/SHM) File databaseDir = context.getDatabasePath("users.db").getParentFile(); if (databaseDir != null) { for (File file : databaseDir.listFiles()) { if (file.getName().startsWith("users.db")) { file.delete(); } } } } }package com.example.kucun2.ui.moban; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; import android.annotation.SuppressLint; import android.content.Context; import android.content.Intent; import android.graphics.Rect; import android.os.Bundle; import android.text.Editable; import android.text.TextUtils; import android.text.TextWatcher; import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.view.ViewTreeObserver; import android.view.animation.DecelerateInterpolator; import android.widget.Button; import android.widget.CheckBox; import android.widget.EditText; import android.widget.ImageButton; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; import android.widget.Toast; import androidx.appcompat.app.AppCompatActivity; import androidx.core.content.ContextCompat; import com.example.kucun2.Http.HttpApi; import com.example.kucun2.Http.ReturnMethod; import com.example.kucun2.R; import com.example.kucun2.data.AppDatabase; import com.example.kucun2.entity.User; import com.example.kucun2.manager.AuthManager; import java.io.File; public class MainActivity extends AppCompatActivity implements View.OnClickListener, View.OnFocusChangeListener, ViewTreeObserver.OnGlobalLayoutListener, TextWatcher { private String TAG = "ifu25"; private ImageButton mIbNavigationBack; private LinearLayout mLlLoginPull; private View mLlLoginLayer; private LinearLayout mLlLoginOptions; private EditText mEtLoginUsername; private EditText mEtLoginPwd; private LinearLayout mLlLoginUsername; private ImageView mIvLoginUsernameDel; private Button mBtLoginSubmit; private LinearLayout mLlLoginPwd; private ImageView mIvLoginPwdDel; private ImageView mIvLoginLogo; private LinearLayout mLayBackBar; private TextView mTvLoginForgetPwd; private Button mBtLoginRegister; private CheckBox cbAgree; //全局Toast private Toast mToast; private int mLogoHeight; private int mLogoWidth; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_login); initView(); } //初始化视图 private void initView() { //登录层、下拉层、其它登录方式层 mLlLoginPull = findViewById(R.id.ll_login_pull); mLlLoginOptions = findViewById(R.id.ll_login_options); //导航栏+返回按钮 mLayBackBar = findViewById(R.id.ly_retrieve_bar); mIbNavigationBack = findViewById(R.id.ib_navigation_back); //logo mIvLoginLogo = findViewById(R.id.iv_login_logo); //username mLlLoginUsername = findViewById(R.id.ll_login_username); mEtLoginUsername = findViewById(R.id.et_login_username); mIvLoginUsernameDel = findViewById(R.id.iv_login_username_del); //passwd mLlLoginPwd = findViewById(R.id.ll_login_pwd); mEtLoginPwd = findViewById(R.id.et_login_pwd); mIvLoginPwdDel = findViewById(R.id.iv_login_pwd_del); //提交、注册 mBtLoginSubmit = findViewById(R.id.bt_login_submit); //忘记密码 mTvLoginForgetPwd = findViewById(R.id.tv_login_forget_pwd); mTvLoginForgetPwd.setOnClickListener(this); //注册点击事件 mLlLoginPull.setOnClickListener(this); mIbNavigationBack.setOnClickListener(this); mEtLoginUsername.setOnClickListener(this); mIvLoginUsernameDel.setOnClickListener(this); mBtLoginSubmit.setOnClickListener(this); mEtLoginPwd.setOnClickListener(this); mIvLoginPwdDel.setOnClickListener(this); findViewById(R.id.ib_login_weibo).setOnClickListener(this); findViewById(R.id.ib_login_qq).setOnClickListener(this); findViewById(R.id.ib_login_wx).setOnClickListener(this); //注册其它事件 mLayBackBar.getViewTreeObserver().addOnGlobalLayoutListener(this); mEtLoginUsername.setOnFocusChangeListener(this); mEtLoginUsername.addTextChangedListener(this); mEtLoginPwd.setOnFocusChangeListener(this); mEtLoginPwd.addTextChangedListener(this); cbAgree = findViewById(R.id.cb_remember_login); cbAgree.setOnCheckedChangeListener((buttonView, isChecked) -> { if (isChecked) { Toast.makeText(this, "已同意协议", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(this, "请阅读并同意协议", Toast.LENGTH_SHORT).show(); } }); } @SuppressLint("NonConstantResourceId") @Override public void onClick(View view) { switch (view.getId()) { case R.id.ib_navigation_back: //返回 finish(); break; case R.id.et_login_username: mEtLoginPwd.clearFocus(); mEtLoginUsername.setFocusableInTouchMode(true); mEtLoginUsername.requestFocus(); break; case R.id.et_login_pwd: mEtLoginUsername.clearFocus(); mEtLoginPwd.setFocusableInTouchMode(true); mEtLoginPwd.requestFocus(); break; case R.id.iv_login_username_del: //清空用户名 mEtLoginUsername.setText(null); break; case R.id.iv_login_pwd_del: //清空密码 mEtLoginPwd.setText(null); break; case R.id.bt_login_submit: //登录 loginRequest(); break; case R.id.tv_login_forget_pwd: //忘记密码 startActivity(new Intent(MainActivity.this, ForgetPwdActivity.class)); break; case R.id.ll_login_pull: mLlLoginPull.animate().cancel(); mLlLoginLayer.animate().cancel(); int height = mLlLoginOptions.getHeight(); float progress = (mLlLoginLayer.getTag() != null && mLlLoginLayer.getTag() instanceof Float) ? (float) mLlLoginLayer.getTag() : 1; int time = (int) (360 * progress); if (mLlLoginPull.getTag() != null) { mLlLoginPull.setTag(null); glide(height, progress, time); } else { mLlLoginPull.setTag(true); upGlide(height, progress, time); } break; case R.id.ib_login_weibo: weiboLogin(); break; case R.id.ib_login_qq: qqLogin(); break; case R.id.ib_login_wx: weixinLogin(); break; default: break; } } //用户名密码焦点改变 @Override public void onFocusChange(View v, boolean hasFocus) { int id = v.getId(); if (id == R.id.et_login_username) { if (hasFocus) { mLlLoginUsername.setActivated(true); mLlLoginPwd.setActivated(false); } } else { if (hasFocus) { mLlLoginPwd.setActivated(true); mLlLoginUsername.setActivated(false); } } } /** * menu glide * * @param height height * @param progress progress * @param time time */ private void glide(int height, float progress, int time) { mLlLoginPull.animate() .translationYBy(height - height * progress) .translationY(height) .setDuration(time) .start(); mLlLoginLayer.animate() .alphaBy(1 * progress) .alpha(0) .setDuration(time) .setListener(new AnimatorListenerAdapter() { @Override public void onAnimationCancel(Animator animation) { if (animation instanceof ValueAnimator) { mLlLoginLayer.setTag(((ValueAnimator) animation).getAnimatedValue()); } } @Override public void onAnimationEnd(Animator animation) { if (animation instanceof ValueAnimator) { mLlLoginLayer.setTag(((ValueAnimator) animation).getAnimatedValue()); } mLlLoginLayer.setVisibility(View.GONE); } }) .start(); } /** * menu up glide * * @param height height * @param progress progress * @param time time */ private void upGlide(int height, float progress, int time) { mLlLoginPull.animate() .translationYBy(height * progress) .translationY(0) .setDuration(time) .start(); mLlLoginLayer.animate() .alphaBy(1 - progress) .alpha(1) .setDuration(time) .setListener(new AnimatorListenerAdapter() { @Override public void onAnimationStart(Animator animation) { mLlLoginLayer.setVisibility(View.VISIBLE); } @Override public void onAnimationCancel(Animator animation) { if (animation instanceof ValueAnimator) { mLlLoginLayer.setTag(((ValueAnimator) animation).getAnimatedValue()); } } @Override public void onAnimationEnd(Animator animation) { if (animation instanceof ValueAnimator) { mLlLoginLayer.setTag(((ValueAnimator) animation).getAnimatedValue()); } } }) .start(); } //显示或隐藏logo @Override public void onGlobalLayout() { final ImageView ivLogo = this.mIvLoginLogo; Rect KeypadRect = new Rect(); mLayBackBar.getWindowVisibleDisplayFrame(KeypadRect); int screenHeight = mLayBackBar.getRootView().getHeight(); int keypadHeight = screenHeight - KeypadRect.bottom; //隐藏logo if (keypadHeight > 300 && ivLogo.getTag() == null) { final int height = ivLogo.getHeight(); final int width = ivLogo.getWidth(); this.mLogoHeight = height; this.mLogoWidth = width; ivLogo.setTag(true); ValueAnimator valueAnimator = ValueAnimator.ofFloat(1, 0); valueAnimator.setDuration(400).setInterpolator(new DecelerateInterpolator()); valueAnimator.addUpdateListener(animation -> { float animatedValue = (float) animation.getAnimatedValue(); ViewGroup.LayoutParams layoutParams = ivLogo.getLayoutParams(); layoutParams.height = (int) (height * animatedValue); layoutParams.width = (int) (width * animatedValue); ivLogo.requestLayout(); ivLogo.setAlpha(animatedValue); }); if (valueAnimator.isRunning()) { valueAnimator.cancel(); } valueAnimator.start(); } //显示logo else if (keypadHeight < 300 && ivLogo.getTag() != null) { final int height = mLogoHeight; final int width = mLogoWidth; ivLogo.setTag(null); ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1); valueAnimator.setDuration(400).setInterpolator(new DecelerateInterpolator()); valueAnimator.addUpdateListener(animation -> { float animatedValue = (float) animation.getAnimatedValue(); ViewGroup.LayoutParams layoutParams = ivLogo.getLayoutParams(); layoutParams.height = (int) (height * animatedValue); layoutParams.width = (int) (width * animatedValue); ivLogo.requestLayout(); ivLogo.setAlpha(animatedValue); }); if (valueAnimator.isRunning()) { valueAnimator.cancel(); } valueAnimator.start(); } } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { } //用户名密码输入事件 @Override public void afterTextChanged(Editable s) { String username = mEtLoginUsername.getText().toString().trim(); String pwd = mEtLoginPwd.getText().toString().trim(); //是否显示清除按钮 if (username.length() > 0) { mIvLoginUsernameDel.setVisibility(View.VISIBLE); } else { mIvLoginUsernameDel.setVisibility(View.INVISIBLE); } if (pwd.length() > 0) { mIvLoginPwdDel.setVisibility(View.VISIBLE); } else { mIvLoginPwdDel.setVisibility(View.INVISIBLE); } //登录按钮是否可用 if (!TextUtils.isEmpty(pwd) && !TextUtils.isEmpty(username)) { mBtLoginSubmit.setBackgroundResource(R.drawable.bg_login_submit); mBtLoginSubmit.setTextColor(ContextCompat.getColor(this,R.color.white)); } else { mBtLoginSubmit.setBackgroundResource(R.drawable.bg_login_submit_lock); mBtLoginSubmit.setTextColor(ContextCompat.getColor(this,R.color.account_lock_font_color)); } } //登录 private void loginRequest() { AppDatabase.deleteDatabase(this); // 验证是否删除成功 File dbFile = this.getDatabasePath("users.db"); if (!dbFile.exists()) { Log.d("Database", "数据库已彻底删除"); } String andy=mEtLoginUsername.getText().toString(); String pass=mEtLoginPwd.getText().toString(); Context context=this; try { HttpApi.HttpPost(getString(R.string.url_baidu), new User(0, null, andy, pass, 0), new ReturnMethod() { @Override public void Success(String data) { Log.d("success",data); // Toast.makeText(MainActivity.this, data, Toast.LENGTH_SHORT).show(); User user =new User(0,"12323123","3211231","12312",0); AuthManager Auth=new AuthManager(context); Auth.register(user) ; Log.d("sql",""+ user.toString()); Log.d("sql",""+ Auth.login(user.getAndy(),user.getPass()) ); } @Override public void failed(String data) { } @Override public void error(Exception e) { // Toast.makeText(MainActivity.this, e.getLocalizedMessage(), Toast.LENGTH_LONG).show(); Log.d("error",e.getLocalizedMessage()); } }); } catch (IllegalAccessException e) { throw new RuntimeException(e); } } //微博登录 private void weiboLogin() { } //QQ登录 private void qqLogin() { } //微信登录 private void weixinLogin() { } /** * 显示Toast * * @param msg 提示信息内容 */ private void showToast(int msg) { if (null != mToast) { mToast.setText(msg); } else { mToast = Toast.makeText(MainActivity.this, msg, Toast.LENGTH_SHORT); } mToast.show(); } } package com.example.kucun2.entity; import androidx.room.Entity; import androidx.room.Ignore; import androidx.room.PrimaryKey; @Entity(tableName = "users") public class User { @PrimaryKey(autoGenerate = true) private Integer id; private String name; private String andy; private String pass; private Integer role; public int getId() { return id; } public String getName() { return name; } public String getAndy() { return andy; } public String getPass() { return pass; } public int getRole() { return role; } public void setId(int id) { this.id = id; } public void setName(String name) { this.name = name; } public void setAndy(String andy) { this.andy = andy; } public void setPass(String pass) { this.pass = pass; } public void setRole(int role) { this.role = role; } @Ignore public User(int id, String name, String andy, String pass, int role) { this.id = id; this.name = name; this.andy = andy; this.pass = pass; this.role = role; } public User() { } @Override public String toString() { StringBuilder sb = new StringBuilder("{"); // 处理属性名 sb.append("\"id\": "); // 处理不同数据类型 // 其他对象类型 sb.append((id != null) ? id : "null"); sb.append(","); // 处理属性名 sb.append("\"name\": "); // 处理不同数据类型 // 字符串类型处理(含转义) sb.append("\"") .append(name .replace("\\", "\\\\") .replace("\"", "\\\"") .replace("\b", "\\b") .replace("\f", "\\f") .replace("\n", "\\n") .replace("\r", "\\r") .replace("\t", "\\t")) .append("\""); sb.append(","); // 处理属性名 sb.append("\"andy\": "); // 处理不同数据类型 // 字符串类型处理(含转义) sb.append("\"") .append(andy .replace("\\", "\\\\") .replace("\"", "\\\"") .replace("\b", "\\b") .replace("\f", "\\f") .replace("\n", "\\n") .replace("\r", "\\r") .replace("\t", "\\t")) .append("\""); sb.append(","); // 处理属性名 sb.append("\"pass\": "); // 处理不同数据类型 // 字符串类型处理(含转义) sb.append("\"") .append(pass .replace("\\", "\\\\") .replace("\"", "\\\"") .replace("\b", "\\b") .replace("\f", "\\f") .replace("\n", "\\n") .replace("\r", "\\r") .replace("\t", "\\t")) .append("\""); sb.append(","); // 处理属性名 sb.append("\"role\": "); // 处理不同数据类型 // 其他对象类型 sb.append((role != null) ? role : "null"); sb.append("}"); return sb.toString(); } } package com.example.kucun2.manager; import android.content.Context; import androidx.room.Room; import com.example.kucun2.data.AppDatabase; import com.example.kucun2.data.UserDao; import com.example.kucun2.entity.User; import at.favre.lib.crypto.bcrypt.BCrypt; public class AuthManager { private final BCrypt.Hasher hasher = BCrypt.with(BCrypt.Version.VERSION_2Y); private final UserDao userDao; public AuthManager(Context context) { AppDatabase db = Room.databaseBuilder( context, AppDatabase.class, "app-db" ).build(); userDao = db.userDao(); } public boolean register(User user) { // 密码强度校验 if (!validatePassword(user.getPass())) return false; // 生成BCrypt哈希(自动处理盐值) String hash = hasher.hashToString(12, user.getPass().toCharArray()); // 异步插入数据库 new Thread(() -> { User us = new User(0,"000000",user.getAndy(),hash,0); userDao.insertUser(us); }).start(); return true; } private boolean validatePassword(String password) { return password.length() >= 8 && password.matches(".*[A-Z].*") && password.matches(".*\\d.*"); } public boolean login(String username, String password) { User user = userDao.findUserByUsername(username); if (user == null) return false; BCrypt.Result result = BCrypt.verifyer().verify( password.toCharArray(), user.getPass() ); return result.verified; } }
05-31
//这个函数不许改,也禁止废话,属性名和其他命名都哼规范不会出现意外, function resolveDataReferences(data) { console.log(data) // 获取 data 对象的所有顶层键 const keys = Object.keys(data); // 遍历每个顶层键(如 users, posts 等) for (const key of keys) { const entities = data[key]; // 遍历该顶层键下的每个实体(如每个 user 或 post) for (const entity of entities) { // 遍历实体的每个属性 for (const attribute in entity) { if (entity?.hasOwnProperty(attribute)) { var trpe=attribute?.replace(/\d/g, ''); // 确保属性属于当前实体 if (Array.isArray(entity[attribute])) { if(data[trpe]==null){ trpe+="s" } // 如果属性是一个数组,则将数组中的每个 ID 替换为对应的实际对象 entity[attribute] = entity[attribute].map(item => data[trpe ]?.find(updateItem => updateItem?.id === item?.id) || item ); } else if (typeof entity[attribute] === "object" && entity[attribute] !== null) { // 如果属性是一个对象,则将其替换为对应的实际对象 entity[attribute] = data[trpe + "s"]?.find(updateItem => updateItem?.id === entity[attribute]?.id); } } } } } return data; } function resolveDataReference(entity,data) { console.log(entity) // // 遍历实体的每个属性 for (const attribute in entity) { if (entity?.hasOwnProperty(attribute)) { var trpe=attribute?.replace(/\d/g, ''); // 确保属性属于当前实体 if (Array.isArray(entity[attribute])) { if(data[trpe]==null){ trpe+="s" } // 如果属性是一个数组,则将数组中的每个 ID 替换为对应的实际对象 entity[attribute] = entity[attribute].map(item => data[trpe ]?.find(updateItem => updateItem?.id === item?.id) || item ); } else if (typeof entity[attribute] === "object" && entity[attribute] !== null) { // 如果属性是一个对象,则将其替换为对应的实际对象 entity[attribute] = data[trpe + "s"]?.find(updateItem => updateItem?.id === entity[attribute]?.id); } } } return entity; } /** * 数据管理器类,负责与后端API通信并管理数据 */ class DataManager { constructor(baseUrl) { this.baseUrl = baseUrl; this.data = { bancais: [], dingdans: [], mupis: [], chanpins: [], kucuns: [], dingdan_bancais:[], chanpin_zujians: [], zujians: [], caizhis: [], dingdan_chanpins: [], users: [], jinhuos: [] }; this.isSyncing = false; this.lastSync = null; this.callbacks = { all: [], bancais: [], dingdan: [], mupi: [], chanpin: [], kucun: [], chanpin_zujian: [], dingdan_bancai:[], zujian: [], caizhi: [], dingdan_chanpin: [], user: [], jinhuo: [] }; this.syncQueue = Promise.resolve(); this.syncInterval = 5 * 60 * 1000; // 5分钟 this.startAutoSync(); this.registerCallback('dingdan_bancai', async (operation, data) => { if (operation === 'add' || operation === 'update') { try { // 构造进货记录数据 const jinhuoData = { dingdan_bancai:{id:data?.id}, shuliang: data.shuliang, date: new Date().toISOString(), user: { id: localStorage.getItem("userId") } }; // 创建进货记录 await this.addEntity('jinhuo', jinhuoData); } catch (error) { console.error('进货记录创建失败:', error); } } }); } // 启动自动同步 startAutoSync() { if (this.autoSyncTimer) clearInterval(this.autoSyncTimer); this.autoSyncTimer = setInterval(() => { if (!this.isSyncing) this.syncData(); }, this.syncInterval); } // 停止自动同步 stopAutoSync() { clearInterval(this.autoSyncTimer); } /** * 获取所有数据 * @returns {Promise<boolean>} 是否成功 */ async fetchAll() { console.log(this) try { const response = await fetch(`${this.baseUrl}/app/all`); if (!response.ok) throw new Error('Network response was not ok'); const result = await response.json(); if (result.status !== 200) throw new Error(result.text || 'API error'); console.log(result.data) const resolvedData = resolveDataReferences(result.data); // 更新本地数据 Object.keys(this.data).forEach(key => { if (resolvedData[key]) { this.data[key] = resolvedData[key]; } }); this.lastSync = new Date(); // 关键改进:数据更新后触发刷新回调 this.triggerCallbacks('refresh', 'all', this.data); return true; } catch (error) { console.error('Fetch error:', error); // 触发错误回调 this.triggerCallbacks('fetch_error', 'all', { error }); return false; } } /** * 注册回调函数 * @param {string} entity - 实体类型(如'bancai')或'all'表示全局回调 * @param {Function} callback - 回调函数,参数为(operation, data) */ registerCallback(entity, callback) { if (!this.callbacks[entity]) { this.callbacks[entity] = []; } this.callbacks[entity].push(callback); } /** * 移除回调函数 * @param {string} entity - 实体类型单数性质 * @param {Function} callback - 要移除的回调函数 */ unregisterCallback(entity, callback) { if (!this.callbacks[entity]) return; const index = this.callbacks[entity].indexOf(callback); if (index !== -1) { this.callbacks[entity].splice(index, 1); } } /** * 触发回调 * @param {string} operation - 操作类型('add', 'update', 'delete') * @param {string} entity - 实体类型单数性质 * @param {Object} data - 相关数据 */ triggerCallbacks(operation, entity, data) { // 触发全局回调 this.callbacks.all.forEach(cb => cb(operation, entity, data)); // 触发特定实体回调 if (this.callbacks[entity]) { this.callbacks[entity].forEach(cb => cb(operation, data)); } } checkDuplicate(entity, data) { switch (entity) { case 'bancai': return this.data.bancais.some(b => b.houdu === data.houdu && b.caizhi?.id === data.caizhi?.id && b.mupi1?.id === data.mupi1?.id && b.mupi2?.id === data.mupi2?.id ); case 'caizhi': return this.data.caizhis.some(c => c.name === data.name); case 'mupi': return this.data.mupis.some(m => m.name === data.name); case 'chanpin': return this.data.chanpins.some(c => c.bianhao === data.bianhao); case 'zujian': return this.data.zujians.some(z => z.name === data.name); case 'dingdan': return this.data.dingdans.some(d => d.number === data.number); case 'chanpin_zujian': return this.data.chanpin_zujians.some(cz => cz.chanpin?.id === data.chanpin?.id && cz.zujian?.id === data.zujian?.id ); case 'dingdan_chanpin': return this.data.dingdan_chanpins.some(dc => dc.dingdan?.id === data.dingdan?.id && dc.chanpin?.id === data.chanpin?.id ); case 'dingdan_bancai': return this.data.dingdan_bancais.some(db => db.dingdan?.id === data.dingdan?.id && db.chanpin?.id === data.chanpin?.id && db.zujian?.id === data.zujian?.id && db.bancai?.id === data.bancai?.id ); case 'user': return this.data.users.some(u => u.name === data.name); default: return false; // 其他实体类型不检查重复 } } /** * 执行CRUD操作 * @param {string} operation - 'add', 'delete', 'update' * @param {string} entity - 实体名称单数性质(小写) * @param {Object} data - 要发送的数据 后端要求数据格式为{属性: "值", 关联对象: {id:0}, 关联对象集: [{id:0}]} * @returns {Promise<Object>} 响应结果 */ async crudOperation(operation, entity, data) { try { const response = await fetch(`${this.baseUrl}/app/${operation}/${entity}`, { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify(data) }); if (!response.ok) throw new Error('Network response was not ok'); const result = await response.json(); if (result.status !== 200) throw new Error(result.text || 'API error'); console.log(data)//这了就没有id了 this. updateLocalData(operation, entity, result.data||data) // 自动同步数据 // 同步完成后触发操作回调 this.triggerCallbacks(operation, entity, result.data||data); return result; } catch (error) { console.error('CRUD error:', error); // 触发操作失败的回调 this.triggerCallbacks(`${operation}_error`, entity, { data, error: error.message }); throw error; } } updateLocalData(operation, entity, newData) { var key=entity+"s"; var entitys= this.data[key] switch (operation) { case 'add': entitys.push(resolveDataReference(newData,this.data)) break; case 'update': const index = entitys.findIndex(item => item.id === newData.id); if (index !== -1) { if(entitys[index].id==newData.id){ for(var an in entitys[index]){ entitys[index][an]=newData[an] } } /*报错DataManager.js:312 CRUD error: ReferenceError: collection is not defined at DataManager.updateLocalData (DataManager.js:335:32) at DataManager.crudOperation (DataManager.js:303:13) at async HTMLButtonElement.<anonymous> (tianjia.js:325:21)*/ } else { entitys.push(resolveDataReference(newData,this.data)); } break; case 'delete': const deleteIndex = entitys.findIndex(item => item.id === newData.id); if (deleteIndex !== -1) { entitys.splice(deleteIndex, 1); } break; default: break; } } /** * 自动同步数据(防止频繁请求) */ async syncData() { if (this.isSyncing) { this.pendingSync = true; return; } this.isSyncing = true; try { await this.fetchAll(); } catch (error) { console.error('Sync failed:', error); } finally { this.isSyncing = false; // 处理等待中的同步请求 if (this.pendingSync) { this.pendingSync = false; setTimeout(() => this.syncData(), 1000); } } } /** * 添加实体 * @param {string} entity - 实体名称单数性质 * @param {Object} data - 实体数据 */ async addEntity(entity, data) { // 检查重复数据 if (this.checkDuplicate(entity, data)) { const errorMsg = `${entity}数据重复`; this.triggerCallbacks('duplicate_error', entity, { data, error: errorMsg }); throw new Error(errorMsg); } return this.crudOperation('add', entity, data); } /** * 更新实体 * @param {string} entity - 实体名称单数性质 * @param {Object} data - 实体数据(必须包含id) */ async updateEntity(entity, data) { return this.crudOperation('update', entity, data); } /** * 删除实体 * @param {string} entity - 实体名称单数性质 * @param {number} id - 实体ID */ async deleteEntity(entity, id) { return this.crudOperation('delete', entity, {id}); } /** * 新增方法:手动触发数据刷新 */ async refreshData() { return this.syncQueue = this.syncQueue.then(() => this.syncData()); } /** * 获取订单的可用板材信息 * @param {number} dingdanId - 订单ID * @returns {Object} 可用板材信息 */ getAvailableBancaisForOrder(dingdanId) { const dingdan = this.data.dingdans.find(d => d?.id == dingdanId); if (!dingdan) return {}; return dingdan.availableBancais || {}; } /** * 获取产品的组件列表 * @param {number} chanpinId - 产品ID * @returns {Array} 组件列表 */ getZujiansForChanpin(chanpinId) { const chanpin = this.data.chanpins.find(c => c?.id == chanpinId); if (!chanpin) return []; return (chanpin.chanpin_zujian_list || []) .map(cz => cz.zujian) .filter(z => z); } /** * 获取组件的板材信息 * @param {number} zujianId - 组件ID * @returns {Array} 板材列表 */ getBancaisForZujian(zujianId) { return (this.data.chanpin_zujians || []) .filter(cz => cz.zujian && cz.zujian?.id == zujianId) .map(cz => cz.bancai) .filter(b => b); } /** * 创建进货记录 * @param {Object} jinhuoData - 进货数据 * @returns {Promise} 操作结果 */ async createJinhuo(jinhuoData) { return this.addEntity('jinhuo', jinhuoData); } /** * 获取订单列表 * @returns {Array} 订单列表 */ getDingdans() { return this.data.dingdans || []; } /** * 获取订单的产品列表 * @param {number} dingdanId - 订单ID * @returns {Array} 产品列表 */ getChanpinsForDingdan(dingdanId) { const dingdan = this.data.dingdans.find(d => d?.id == dingdanId); if (!dingdan) return []; return (dingdan.dingdan_chanpin_list || []) .map(dc => dc.chanpin) .filter(c => c); } } export { DataManager }; // 创建单例实例 //const dataManager = new DataManager('http://127.0.0.1:8080/KuCun2'); //// 初始化时获取所有数据 //dataManager.fetchAll().then(() => { // console.log('Initial data loaded'); //}); // 导出数据对象,外部可以直接访问 data.bancais, data.dingdans 等 //export const data = dataManager.data; //// 导出操作方法 //export const addEntity = dataManager.addEntity.bind(dataManager); //export const updateEntity = dataManager.updateEntity.bind(dataManager); //export const deleteEntity = dataManager.deleteEntity.bind(dataManager); //export const fetchAll = dataManager.fetchAll.bind(dataManager);////////---------------------================获取数据时去重和更新
最新发布
06-27
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值