Eclipse+Java+Swing+Mysql实现进销存管理系统建议收藏
Posted 水坚石青
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Eclipse+Java+Swing+Mysql实现进销存管理系统建议收藏相关的知识,希望对你有一定的参考价值。
目录
一、系统介绍
1.开发环境
开发工具:Eclipse2021
JDK版本:jdk1.8
mysql版本:8.0.13
2.技术选型
Java+Swing+Mysql
3.系统功能
1.登录系统
2.商品管理
3.入库管理
4.出库管理
5.仓库管理
6.用户管理
4.数据库
/*
Navicat Premium Data Transfer
Source Server : MYSQL
Source Server Type : MySQL
Source Server Version : 80013
Source Host : localhost:3306
Source Schema : swing_sales
Target Server Type : MySQL
Target Server Version : 80013
File Encoding : 65001
Date: 26/10/2021 10:56:13
*/
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for category
-- ----------------------------
DROP TABLE IF EXISTS `category`;
CREATE TABLE `category` (
`id` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`del_flag` int(2) NOT NULL DEFAULT 0,
PRIMARY KEY (`del_flag`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of category
-- ----------------------------
INSERT INTO `category` VALUES ('1', '京东', 0);
-- ----------------------------
-- Table structure for goods
-- ----------------------------
DROP TABLE IF EXISTS `goods`;
CREATE TABLE `goods` (
`id` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`price` double(100, 2) NULL DEFAULT NULL,
`origin` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`stock` double(100, 2) NULL DEFAULT NULL,
`warehouse_id` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`category_id` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`del_flag` int(2) NOT NULL DEFAULT 0
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of goods
-- ----------------------------
INSERT INTO `goods` VALUES ('817fbfa3668446c3909bc11d9b5e0c13', '方便面', 31.00, 'jd.com', 0.00, 'e097dc68778d4ee78bb7b6b6f9401799', '1', 0);
INSERT INTO `goods` VALUES ('b8679e3e00884f318106cf7c34f71847', '面包', 4.00, 'jd.com', 5.00, 'e097dc68778d4ee78bb7b6b6f9401799', '1', 0);
INSERT INTO `goods` VALUES ('839cbdbb41e745f796dfe43414b0bdd8', '1', 1.00, '1', 1.00, 'e097dc68778d4ee78bb7b6b6f9401799', '1', 1);
-- ----------------------------
-- Table structure for sale_order
-- ----------------------------
DROP TABLE IF EXISTS `sale_order`;
CREATE TABLE `sale_order` (
`id` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`bill_no` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`amount` double(3, 2) NULL DEFAULT NULL,
`handler_id` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`category_id` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`warehouse_id` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`goods_id` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`del_flag` int(2) NULL DEFAULT NULL
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of sale_order
-- ----------------------------
INSERT INTO `sale_order` VALUES ('db320bc2d5814563a8f901a719762ad4', '17041918530001', 2.00, '1', '1', 'e097dc68778d4ee78bb7b6b6f9401799', '817fbfa3668446c3909bc11d9b5e0c13', NULL);
INSERT INTO `sale_order` VALUES ('47ab9845e6aa4f8f922c4afca71bc8d1', '21102609210002', 2.00, '1', '1', 'e097dc68778d4ee78bb7b6b6f9401799', '817fbfa3668446c3909bc11d9b5e0c13', NULL);
-- ----------------------------
-- Table structure for stock_order
-- ----------------------------
DROP TABLE IF EXISTS `stock_order`;
CREATE TABLE `stock_order` (
`id` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`bill_no` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`handler_id` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`warehouse_id` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`category_id` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`amount` double NULL DEFAULT NULL,
`goods_id` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`sign` int(10) NULL DEFAULT NULL,
`del_flag` int(2) NOT NULL DEFAULT 0
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of stock_order
-- ----------------------------
INSERT INTO `stock_order` VALUES ('2500244829bb4e6ab4c5fb71a98626bc', '17041918530002', '1', 'e097dc68778d4ee78bb7b6b6f9401799', '1', 2, '817fbfa3668446c3909bc11d9b5e0c13', 1, 0);
INSERT INTO `stock_order` VALUES ('0a1a2d9e8145484cbda4573279e54a58', '21102609210001', '1', 'e097dc68778d4ee78bb7b6b6f9401799', '1', 2, '817fbfa3668446c3909bc11d9b5e0c13', 0, 0);
INSERT INTO `stock_order` VALUES ('99aa1ed95a214f37a0b1b1a547abe324', '21102609210003', '1', 'e097dc68778d4ee78bb7b6b6f9401799', '1', 2, '817fbfa3668446c3909bc11d9b5e0c13', 1, 0);
-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`password` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`identity` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES ('1', 'admin', 'admin', '1');
-- ----------------------------
-- Table structure for warehouse
-- ----------------------------
DROP TABLE IF EXISTS `warehouse`;
CREATE TABLE `warehouse` (
`id` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`name` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`del_flag` int(2) NOT NULL DEFAULT 0,
`sort` int(2) NULL DEFAULT NULL
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of warehouse
-- ----------------------------
INSERT INTO `warehouse` VALUES ('e097dc68778d4ee78bb7b6b6f9401799', '快销区', 0, NULL);
INSERT INTO `warehouse` VALUES ('24cf1496ebd14beebeb43850285f4e2b', '早餐区', 0, NULL);
SET FOREIGN_KEY_CHECKS = 1;
二、系统展示
1.登录系统
2.首页
3.商品查看
4.商品新增
5.商品修改
6.入库管理
7.出库管理
8.仓库管理
9.用户管理
三、部分代码
CategoryServiceImpl
package org.rancode.module.services.Impl;
import java.util.List;
import org.rancode.module.dao.Impl.BaseDaoImpl;
import org.rancode.module.services.CategoryService;
public class CategoryServiceImpl implements CategoryService {
// 查询所有分类
@Override
public List selectAll() throws Exception {
BaseDaoImpl dao = new BaseDaoImpl();
List list = dao.select("select id,name from category where 1=1 and del_flag='0' ", 2, null);
if (!list.isEmpty()) {
return list;
}
return null;
}
}
GoodsServiceImpl
package org.rancode.module.services.Impl;
import java.util.List;
import java.util.Vector;
import org.rancode.module.dao.Impl.BaseDaoImpl;
import org.rancode.module.services.GoodsService;
public class GoodsServiceImpl implements GoodsService {
// 条件查询商品
@Override
public Vector<Vector> selectByCondition(Object[] paraArray) throws Exception {
Vector<Vector> rows = new Vector<Vector>();
BaseDaoImpl dao = new BaseDaoImpl();
StringBuilder sqlBuilder = new StringBuilder(
"select g.id,g.name,g.price,g.origin,c.name as categoryName,w.name as warehouseName, g.stock,w.id as warehouseId,c.id as categoryId "
+ "from goods g,warehouse w,category c "
+ "where 1=1 and g.del_flag='0' and w.del_flag='0' and c.del_flag='0' and g.warehouse_id=w.id and g.category_id=c.id ");
if (!"全部".equals(paraArray[0])) {
sqlBuilder.append(" and g.category_id='" + paraArray[0] + "'");
}
if (!"全部".equals(paraArray[1])) {
sqlBuilder.append(" and g.warehouse_id='" + paraArray[1] + "'");
}
String sql = sqlBuilder.toString();
List<Object[]> list = dao.select(sql, 9, null);
if (!list.isEmpty()) {
for (Object[] object : list) {
Vector temp = new Vector<String>();
for (int i = 0; i < object.length; i++) {
temp.add(object[i]);
}
rows.add(temp);
}
}
return rows;
}
// 逻辑删除商品
@Override
public int deleteById(Object[] paraArray) throws Exception {
BaseDaoImpl dao = new BaseDaoImpl();
int result = 0;
result = dao.update("update goods set del_flag='1' where id=?", paraArray);
return result;
}
// 通过id修改销售单
@Override
public int updateById(Object[] paraArray) throws Exception {
BaseDaoImpl dao = new BaseDaoImpl();
int result = 0;
result = dao.update("update goods set name=?,price=?,origin=?,stock=?,warehouse_id=?,category_id=? where id=?",
paraArray);
return result;
}
// 插入销售单
@Override
public int insertById(Object[] paraArray) throws Exception {
BaseDaoImpl dao = new BaseDaoImpl();
int result = 0;
result = dao.insert(
"insert into goods(id,name,price,origin,stock,warehouse_id,category_id,del_flag) values(?,?,?,?,?,?,?,'0')",
paraArray);
return result;
}
// 查询所有销售单
@Override
public List selectAll() throws Exception {
BaseDaoImpl dao = new BaseDaoImpl();
String sql = "select id,name from goods where 1=1 and del_flag='0' ";
List<Object[]> list = dao.select(sql, 2, null);
return list;
}
// 通过id查询销售单
@Override
public List selectById(Object[] paraArray) throws Exception {
BaseDaoImpl dao = new BaseDaoImpl();
String sql = "select c.id,c.name,w.id,w.name,g.stock " + "from goods g,category c,warehouse w "
+ "where g.category_id=c.id and g.warehouse_id=w.id and g.del_flag='0' and c.del_flag='0' and w.del_flag='0' and g.id=?";
List<Object[]> list = dao.select(sql, 5, paraArray);
return list;
}
// 通过id修改库存
@Override
public int updateStockById(Object[] paraArray) throws Exception {
BaseDaoImpl dao = new BaseDaoImpl();
int result = 0;
result = dao.update("update goods set stock=stock+? where id=?", paraArray);
return result;
}
}
SaleOrderServiceImpl
package org.rancode.module.services.Impl;
import java.util.List;
import java.util.Vector;
import org.rancode.module.dao.Impl.BaseDaoImpl;
import org.rancode.module.services.SaleOrderService;
public class SaleOrderServiceImpl implements SaleOrderService {
// 条件查询销售单
@Override
public Vector<Vector> selectByCondition(Object[] paraArray) throws Exception {
Vector<Vector> rows = new Vector<Vector>();
BaseDaoImpl dao = new BaseDaoImpl();
StringBuilder sqlBuilder = new StringBuilder(
"select s.id,s.bill_no,g.name,s.amount,c.name,w.name,u.name,c.id,w.id "
+ " from sale_order s,user u,goods g,category c,warehouse w "
+ " where s.handler_id=u.id and s.category_id=c.id and s.warehouse_id=w.id and s.goods_id=g.id and s.del_flag='0' and g.del_flag='0' and c.del_flag='0' and w.del_flag='0'");
String name = paraArray[0].toString().trim();
if (!name.isEmpty()) {
sqlBuilder.append(" and g.name like '%" + paraArray[0] + "%' ");
}
if (!"全部".equals(paraArray[1])) {
sqlBuilder.append(" and s.category_id='" + paraArray[1] + "' ");
}
if (!"全部".equals(paraArray[2])) {
sqlBuilder.append(" and s.warehouse_id='" + paraArray[2] + "' ");
}
String sql = sqlBuilder.toString();
List<Object[]> list = dao.select(sql, 9, null);
if (!list.isEmpty()) {
for (Object[] object : list) {
Vector temp = new Vector<String>();
for (int i = 0; i < object.length; i++) {
temp.add(object[i]);
}
rows.add(temp);
}
}
return rows;
}
// 插入销售单
@Override
public int insert(Object[] paraArray) throws Exception {
BaseDaoImpl dao = new BaseDaoImpl();
int result = 0;
result = dao.insert(
"insert into sale_order(id,bill_no,handler_id,category_id,warehouse_id,amount,goods_id) values(?,?,?,?,?,?,?)",
paraArray);
return result;
}
}
StockOrderServiceImpl
package org.rancode.module.services.Impl;
import java.util.List;
import java.util.Vector;
import org.rancode.module.dao.Impl.BaseDaoImpl;
import org.rancode.module.services.StockOrderService;
public class StockOrderServiceImpl implements StockOrderService {
// 条件查询入库单
@Override
public Vector<Vector> selectStockInputByCondition(Object[] paraArray) throws Exception {
Vector<Vector> rows = new Vector<Vector>();
BaseDaoImpl dao = new BaseDaoImpl();
StringBuilder sqlBuilder = new StringBuilder(
"select s.id,s.bill_no,g.name,s.amount,c.name,w.name,u.name,c.id,w.id "
+ " from stock_order s,goods g,user u,category c,warehouse w "
+ " where s.handler_id=u.id and s.goods_id=g.id and s.category_id=c.id and s.warehouse_id=w.id and s.sign='0' and s.del_flag='0' and g.del_flag='0' and c.del_flag=0 and w.del_flag='0' ");
String name = paraArray[0].toString().trim();
if (!name.isEmpty()) {
sqlBuilder.append(" and g.name like '%" + paraArray[0] + "%' ");
}
if (!"全部".equals(paraArray[1])) {
sqlBuilder.append(" and s.category_id='" + paraArray[1] + "' ");
}
if (!"全部".equals(paraArray[2])) {
sqlBuilder.append(" and s.warehouse_id='" + paraArray[2] + "' ");
}
if (!"全部".equals(paraArray[3])) {
sqlBuilder.append(" and s.handler_id='" + paraArray[3] + "' ");
}
String sql = sqlBuilder.toString();
List<Object[]> list = dao.select(sql, 9, null);
if (!list.isEmpty()) {
for (Object[] object : list) {
Vector temp = new Vector<String>();
for (int i = 0; i < object.length; i++) {
temp.add(object[i]);
}
rows.add(temp);
}
}
return rows;
}
// 通过id逻辑删除入库单
@Override
public int deleteStockInputById(Object[] paraArray) throws Exception {
BaseDaoImpl dao = new BaseDaoImpl();
int result = 0;
result = dao.update("update stock_order set del_flag='1' where id=?", paraArray);
return result;
}
// 通过id修改入库单
@Override
public int updateStockInputById(Object[] paraArray) throws Exception {
BaseDaoImpl dao = new BaseDaoImpl();
int result = 0;
result = dao.update("update stock_order set amount=? where id=?", paraArray);
return result;
}
// 插入入库单
@Override
public int insertStockInput(Object[] paraArray) throws Exception {
BaseDaoImpl dao = new BaseDaoImpl();
int result = 0;
result = dao.insert(
"insert into stock_order(id,bill_no,handler_id,warehouse_id,category_id,amount,goods_id,sign) values(?,?,?,?,?,?,?,'0')",
paraArray);
return result;
}
// 条件查询出库单
@Override
public Vector<Vector> selectStockOutputByCondition(Object[] paraArray) throws Exception {
Vector<Vector> rows = new Vector<Vector>();
BaseDaoImpl dao = new BaseDaoImpl();
StringBuilder sqlBuilder = new StringBuilder(
"select s.id,s.bill_no,g.name,s.amount,c.name,w.name,u.name,c.id,w.id "
+ " from stock_order s,goods g,user u,category c,warehouse w "
+ " where s.handler_id=u.id and s.goods_id=g.id and s.category_id=c.id and s.warehouse_id=w.id and s.sign='1' and s.del_flag='0' and g.del_flag='0' and c.del_flag=0 and w.del_flag='0' ");
String name = paraArray[0].toString().trim();
if (!name.isEmpty()) {
sqlBuilder.append(" and g.name like '%" + paraArray[0] + "%' ");
}
if (!"全部".equals(paraArray[1])) {
sqlBuilder.append(" and s.category_id='" + paraArray[1] + "' ");
}
if (!"全部".equals(paraArray[2])) {
sqlBuilder.append(" and s.warehouse_id='" + paraArray[2] + "' ");
}
if (!"全部".equals(paraArray[3])) {
sqlBuilder.append(" and s.handler_id='" + paraArray[3] + "' ");
}
String sql = sqlBuilder.toString();
List<Object[]> list = dao.select(sql, 9, null);
if (!list.isEmpty()) {
for (Object[] object : list) {
Vector temp = new Vector<String>();
for (int i = 0; i < object.length; i++) {
temp.add(object[i]);
}
rows.add(temp);
}
}
return rows;
}
// 通过id逻辑删除出库单
@Override
public int deleteStockOutputById(Object[] paraArray) throws Exception {
BaseDaoImpl dao = new BaseDaoImpl();
int result = 0;
result = dao.update("update stock_order set del_flag='1' where id=?", paraArray);
return result;
}
// 通过id修改出库单
@Override
public int updateStockOutputById(Object[] paraArray) throws Exception {
BaseDaoImpl dao = new BaseDaoImpl();
int result = 0;
result = dao.update("update stock_order set amount=? where id=?", paraArray);
return result;
}
// 插入出库单
@Override
public int insertStockOutput(Object[] paraArray) throws Exception {
BaseDaoImpl dao = new BaseDaoImpl();
int result = 0;
result = dao.insert(
"insert into stock_order(id,bill_no,handler_id,warehouse_id,category_id,amount,goods_id,sign) values(?,?,?,?,?,?,?,'1')",
paraArray);
return result;
}
}
UserServiceImpl
package org.rancode.module.services.Impl;
import java.util.List;
import org.omg.PortableServer.SERVANT_RETENTION_POLICY_ID;
import org.rancode.module.dao.BaseDao;
import org.rancode.module.dao.Impl.BaseDaoImpl;
import org.rancode.module.entity.User;
import org.rancode.module.services.UserService;
public class UserServiceImpl implements UserService {
// 查询一条记录
@Override
public User selectOne(Object[] paraArray) throws Exception {
User user = new User();
BaseDaoImpl dao = new BaseDaoImpl();
String sql = "select id,name,password,identity from user where name=? and password=?";
List list = dao.select(sql, 4, paraArray);
if (!list.isEmpty()) {
user.setId((String) ((Object[]) list.get(0))[0]);
user.setName((String) ((Object[]) list.get(0))[1]);
user.setPassword((String) ((Object[]) list.get(0))[2]);
user.setIdentity((String) ((Object[]) list.get(0))[3]);
return user;
}
return null;
}
// 通过Id修改用户
@Override
public int updateUserById(Object[] paraArray) throws Exception {
int result = 0;
BaseDaoImpl dao = new BaseDaoImpl();
String sql = "update user set name = ?,password=? where id=?";
result = dao.update(sql, paraArray);
return result;
}
}
WarehouseServiceImpl
package org.rancode.module.services.Impl;
import java.util.List;
import java.util.Vector;
import org.rancode.module.dao.Impl.BaseDaoImpl;
import org.rancode.module.services.WarehouseService;
public class WarehouseServiceImpl implements WarehouseService {
// 遍历所有仓库
@Override
public List selectAll() throws Exception {
BaseDaoImpl dao = new BaseDaoImpl();
List list = dao.select("select id,name from warehouse where 1=1 and del_flag='0' ", 2, null);
if (!list.isEmpty()) {
return list;
}
return null;
}
// 遍历所有仓库返回Vector
@Override
public Vector<Vector> selectAllVexctor() throws Exception {
Vector<Vector> rows = new Vector<Vector>();
BaseDaoImpl dao = new BaseDaoImpl();
List<Object[]> list = dao.select("select id,sort,name from warehouse where 1=1 and del_flag='0' order by sort",
3, null);
if (!list.isEmpty()) {
int number = 1;
for (Object[] object : list) {
Vector temp = new Vector<String>();
for (int i = 0; i < object.length; i++) {
if (i == 1) {
temp.add(number);
} else {
temp.add(object[i]);
}
}
rows.add(temp);
number++;
}
}
return rows;
}
// 通过Id修改仓库
@Override
public int updateById(Object[] paramArray) throws Exception {
int result = 0;
BaseDaoImpl dao = new BaseDaoImpl();
result = dao.update("update warehouse set name=? where id=?", paramArray);
return result;
}
// 通过Id逻辑删除仓库
@Override
public int deleteById(Object[] paramArray) throws Exception {
BaseDaoImpl dao = new BaseDaoImpl();
int result = 0;
result = dao.update("update warehouse set del_flag='1' where id=?", paramArray);
return result;
}
// 插入仓库
@Override
public int insertById(Object[] paramArray) throws Exception {
BaseDaoImpl dao = new BaseDaoImpl();
int result = 0;
result = dao.insert("insert into warehouse(id,name) values(?,?) ", paramArray);
return result;
}
}
四、其他
1.更多系统
更多JavaSwing系统请关注专栏。
https://blog.csdn.net/helongqiang/category_6229101.htmlhttps://blog.csdn.net/helongqiang/category_6229101.html
2.源码下载
3.运行项目
请点击以下链接,部署你的项目。
4.备注
如有侵权请联系我删除。
5.支持博主
如果您觉得此文对您有帮助,请点赞加关注加收藏。祝您生活愉快!想要获取其他资源可关注左侧微信公众号获取!
以上是关于Eclipse+Java+Swing+Mysql实现进销存管理系统建议收藏的主要内容,如果未能解决你的问题,请参考以下文章
Eclipse+Java+Swing+Mysql实现超市管理系统
Eclipse+Java+Swing+Mysql实现酒店管理系统
Eclipse+Java+Swing+Mysql实现学生信息管理系统
Eclipse+Java+Swing+Mysql实现进销存管理系统建议收藏