基于ThinkPHP5+MySQL的超市进销存管理系统

目 录
摘 要 I
Abstract II
1 前 言 1
1.1 项目开发背景 1
1.2 项目开发意义 1
1.3 主要工作 1
2 系统分析 2
2. 1 需求分析 2
2. 2 可行性分析 2
2.2.1 经济可行性 2
2.2.2 技术可行性 2
2.2.3 操作可行性 2
2.2.4 社会可行性 2
3 开发环境 3
3.1 开发工具 3
3.1.1 操作系统 3
3.1.2 数据库 3
3.1.3 开发平台 3
3.1.4 语言框架 3
3.2 系统开发环境 4
4 系统总体设计 5
4.1 系统架构设计 5
4.2 数据结构设计 5
4.2.1 ER图 5
4.2.2 数据描述 9
4.2.3 数据库表设计 9
4. 3 系统功能模块设计 12
4.3.1 系统登陆模块 12
4.3.2 账号管理模块 13
4.3.3 商品分类管理 13
4.3.4 商品管理模块 14
4.3.5 库存管理模块 14
4.3.6 库存日志模块 15
4.3.7 销售管理模块 15
5 系统详细设计 17
5.1 登录 17
5.2 主界面 17
5.2.1 首页 17
5.2.2 个人信息 19
5.3 账号管理 19
5.4 商品分类管理 20
5.4.1 商品分类列表 20
5.4.2 商品分类新增/修改 20
5.5 商品管理 21
5.5.1商品列表 21
5.5.2商品新增/修改 22
5.6 库存管理 22
5.7 库存日志 24
5.8 销售管理 25
5.8.1 商品销售情况 25
5.8.2 报表导出Excel 25
5.9 供应商管理 27
5.9.1 供应商列表 27
5.9.2 供应商新增/编辑 27
6 系统测试 28
6.1 系统测试的目的及意义 28
6.2 测试过程 28
6.2.1 系统登录测试 28
6.2.2 用户新增/编辑、禁用/启用测试 29
6.2.3 商品分类新增/编辑、删除测试 29
6.3 测试结果 29
7 总结 31
参考文献 32
致谢 33
1.2 项目开发意义
本项目旨在为中小型超市开发一款安全高效的管理系统,通过对项目的思考、构架以及项目的实施过程中,可以切身体会到一个项目的流程步骤,为今后的项目设计和开发打下扎实的根底。本项目采用面向对象的思想,在项目代码的编写过程中,通过不断地思考和优化,可以使开发者从面向程序的思维中跳出来,站在更高的角度来思考问题。项目中涉及到大量的数据库操作,可以使开发者熟悉和掌握大量的SQL语言,也让其对数据结构有一个更加深刻的认识和理解。项目前端的界面渲染则要求开发者学习一定的CSS+JS+DIV的页面布局和部分动态网页技巧。
通过本次项目,开发者学习到的不仅仅是独立分析问题、解决问题的技巧,更多的是一种全局观的思维逻辑。
1.3 主要工作
1.网上查找thinkPHP5框架手册,搭建好系统和服务器环境;
2.针对本系统,通过网络和线下调查用户需求;
3.规划系统主体模块,绘出系统模块结构图;
4.对模块进行细化,确定系统数据库结构;
5.创建数据库,实现系统功能;
6.调试系统,整理相关资料,完成论文。
3 开发环境
3.1 开发工具
3.1.1 操作系统
本次项目开发选择了Windows 10家庭版操作系统。Windows 10是美国微软公司于2015年7月份正式推出的一款操作系统。Win10在保留了之前操作系统的优秀特点的基础上,在界面、功能和性能上做出了很大的提升和优化,是一款优秀的操作系统,其独特的任务视图和多虚拟桌面为开发者提供了很大的便利,非常适合开发者。
3.1.2 数据库
数据库(Database)是一种按照数据结构来组织、存储和管理数据的建立在计算机存储设备上的仓库[1]。
严格来说,数据库是长期存储在计算机内、有组织的、可共享的数据集合;数据库中的数据指的是以一定的数据模型组织、描述和存储在一起、具有尽可能小的冗余度、较高的数据独立性和易扩展性的特点并可在一定的范围内为多个用户共享[2]。
这种数据集合具备以下几个方面的特点:尽可能不出现重复,以最优的存储方式和最小的查询代价为某个特定组织的多种应用提供数据存储服务,其数据结构应独立于使用它的应用程序,并且应该尽量只作为存储层,不参与任何逻辑,对数据的增、删、改、查由统一软件进行管理和控制。
数据库的出现,大大地满足了各类型企业对数据维护的需求。如今,数据库已经成为企业日常管理中必不可少的工具。
本系统采用了MySQL数据库,MySQL是一个关系型数据库管理系统,是如今最流行的数据库管理系统之一,灵活性高,处理速度快,非常适用于web应用。
3.1.3 开发平台
系统是在NetBeans IDE+ WampServer的环境下进行开发的。
3.1.3.1 IDE
在软件开发上,IDE一般指集成开发环境(Integrated Development Environment),是用于提供程序开发环境的应用程序,一般包括代码编辑器、编译器、调试器和图形用户界面等工具[3]。
NetBeans IDE是由Sum公司于2000年创立,是一个开源软件开发集成环境,是一个可扩展的开发平台,使用方便,功能强大。本文转载自http://www.biyezuopin.vip/onews.asp?id=15615
3.1.3.2 WampServer
WampServer是一款集成了Apache、MySQL和PHP的服务器软件,拥有简单的图形菜单,可以快捷方便配置开发环境,免去了繁琐的开发环境配置过程。WampServer还同时支持PHPmyadmin,可以通过它来轻松地管理MySQL数据库。
3.1.4 语言框架
在语言框架上,本系统采用了基于PHP语言的ThinkPHP5框架。
3.1.4.1 PHP语言
PHP(PHP:Hypertext Preprocessor)又名“超文本预处理器”,是一种被广泛应用的面向对象的开源脚本语言,它的语法结合了C语言、Perl和Java等语言的特点[4]。PHP可以嵌入到HTML中,非常适合web开发。本文转载自
3.1.4.2 ThinkPHP框架
ThinkPHP是一个免费开源的,简单、快速的,面向对象的轻量级PHP开发框架,遵循Apache2开源协议而发布,是为了敏捷WEB应用开发和简化企业应用开发而诞生的,性能稳定,代码简洁[5]。
3.2 系统开发环境
B/S结构模式,又称“浏览器/服务器模式”是如今web开发中最经典的一种模式,是通过web浏览器作为中转来实现客户端与服务器的互动,将系统的关键部分集中放在服务器上,从而提高系统的稳定性,方便开发和维护。对用户而言,无需任何其他软件,只需安装一个web浏览器即可使用本系统。

<?php
/**
 * tpAdmin [a web admin based ThinkPHP5]
 *
 * @author    yuan1994 <tianpian0805@gmail.com>
 * @link      http://tpadmin.yuan1994.com/
 * @copyright 2016 yuan1994 all rights reserved.
 * @license   http://www.apache.org/licenses/LICENSE-2.0
 */

namespace app\index;

use think\Model;
use think\View;
use think\Request;
use think\Session;
use think\Db;
use think\Config;
use think\Loader;
use think\Exception;
use think\exception\HttpException;
use app\index\logic\Pub as PubLogic;

class Controller
{
    /**
     * @var View 视图类实例
     */
    protected $view;
    /**
     * @var Request Request实例
     */
    protected $request;
    /**
     * @var array 黑名单方法,禁止访问某些方法
     */
    protected static $blacklist = [];
    /**
     * @var array 白名单方法,如果设置会覆盖黑名单方法,只允许白名单方法能正常访问
     */
    protected static $allowList = [];
    /**
     * @var int 是否删除标志,0-正常|1-删除|false-不包含该字段
     */
    protected static $isdelete = 0;
    /**
     * @var string 假删除字段
     */
    protected $fieldIsDelete = 'isdelete';
    /**
     * @var string 状态禁用、恢复字段
     */
    protected $fieldStatus = 'status';

    public function __construct()
    {
        if (null === $this->view) {
            $this->view = View::instance(Config::get('template'), Config::get('view_replace_str'));
        }
        if (null === $this->request) {
            $this->request = Request::instance();
        }

        // 白名单/黑名单方法
        if ($this::$allowList && !in_array($this->request->action(), $this::$allowList)) {
            throw new HttpException(404, 'method not exists:' . $this->request->controller() . '->' . $this->request->action());
        } elseif ($this::$blacklist && in_array($this->request->action(), $this::$blacklist)) {
            throw new HttpException(404, 'method not exists:' . $this->request->controller() . '->' . $this->request->action());
        }

        // 用户ID
        defined('UID') or define('UID', Session::get(Config::get('rbac.user_auth_key')));
        // 是否是管理员
        defined('ADMIN') or define('ADMIN', true === Session::get(Config::get('rbac.admin_auth_key')));

        // 检查认证识别号
        if (null === UID) {
            $this->notLogin();
        } else {
            $this->auth();
        }

        // 前置方法
        $beforeAction = "before" . $this->request->action();
        if (method_exists($this, $beforeAction)) {
            $this->$beforeAction();
        }
    }

    /**
     * 自动搜索查询字段,给模型字段过滤
     */
    protected function search($model, $param = [])
    {
        $map = [];
        $table_info = $model->getTableInfo();
        $param = array_merge($this->request->param(), $param);
        foreach ($param as $key => $val) {
            if ($val !== "" && in_array($key, $table_info['fields'])) {
                $map[$key] = $val;
            }
        }

        return $map;
    }

    /**
     * 获取模型
     *
     * @param string $controller
     * @param bool   $type 是否返回模型的类型
     *
     * @return \think\db\Query|\think\Model|array
     */
    protected function getModel($controller = '', $type = false)
    {
        $module = Config::get('app.model_path');
        if (!$controller) {
            $controller = $this->request->controller();
        }
        if (
            class_exists($modelClass = Loader::parseClass($module, 'model', $this->parseCamelCase($controller)))
            || class_exists($modelClass = Loader::parseClass($module, 'model', $controller))
        ) {
            $model = new $modelClass();
            $modelType = 'model';
        } else {
            $model = Db::name($this->parseTable($controller));
            $modelType = 'db';
        }

        return $type ? ['type' => $modelType, 'model' => $model] : $model;
    }

    /**
     * 获取实际的控制器名称(应用于多层控制器的场景)
     *
     * @param $controller
     *
     * @return mixed
     */
    protected function getRealController($controller = '')
    {
        if (!$controller) {
            $controller = $this->request->controller();
        }
        $controllers = explode(".", $controller);
        $controller = array_pop($controllers);

        return $controller;
    }

    /**
     * 默认更新字段方法
     *
     * @param string     $field 更新的字段
     * @param string|int $value 更新的值
     * @param string     $msg   操作成功提示信息
     * @param string     $pk    主键,默认为主键
     * @param string     $input 接收参数,默认为主键
     */
    protected function updateField($field, $value, $msg = "操作成功", $pk = "", $input = "")
    {
        $model = $this->getModel();
        if (!$pk) {
            $pk = $model->getPk();
        }
        if (!$input) {
            $input = $model->getPk();
        }
        $ids = $this->request->param($input);
        $where[$pk] = ["in", $ids];
        if (false === $model->where($where)->update([$field => $value])) {
            return ajax_return_adv_error($model->getError());
        }

        return ajax_return_adv($msg, '');
    }

    /**
     * 格式化表名,将 /. 转为 _ ,支持多级控制器
     *
     * @param string $name
     *
     * @return mixed
     */
    protected function parseTable($name = '')
    {
        if (!$name) {
            $name = $this->request->controller();
        }

        return str_replace(['/', '.'], '_', $name);
    }

    /**
     * 格式化类名,将 /. 转为 \\
     * 已废弃,请使用Loader::parseClass()
     *
     * @param string $name
     *
     * @return mixed
     */
    protected function parseClass($name = '')
    {
        if (!$name) {
            $name = $this->request->controller();
        }

        return str_replace(['/', '.'], '\\', $name);
    }

    /**
     * 未登录处理
     */
    protected function notLogin()
    {
        PubLogic::notLogin();
    }

    /**
     * 权限校验
     */
    protected function auth()
    {
        // 用户权限检查
        if (
            Config::get('rbac.user_auth_on') &&
            !in_array($this->request->module(), explode(',', Config::get('rbac.not_auth_module')))
        ) {
            if (!\Rbac::AccessCheck()) {
                throw new HttpException(403, "没有权限");
            }
        }
    }

    /**
     * 过滤禁止操作某些主键
     *
     * @param        $filterData
     * @param string $error
     * @param string $method
     * @param string $key
     */
    protected function filterId($filterData, $error = '该记录不能执行此操作', $method = 'in_array', $key = 'id')
    {
        $data = $this->request->param();
        if (!isset($data[$key])) {
            throw new HttpException(404, '缺少必要参数');
        }
        $ids = is_array($data[$key]) ? $data[$key] : explode(",", $data[$key]);
        foreach ($ids as $id) {
            switch ($method) {
                case '<':
                case 'lt':
                    $ret = $id < $filterData;
                    break;
                case '>':
                case 'gt':
                    $ret = $id < $filterData;
                    break;
                case '=':
                case 'eq':
                    $ret = $id == $filterData;
                    break;
                case '!=':
                case 'neq':
                    $ret = $id != $filterData;
                    break;
                default:
                    $ret = call_user_func_array($method, [$id, $filterData]);
                    break;
            }
            if ($ret) {
                throw new Exception($error);
            }
        }
    }

    /**
     * 根据表单生成查询条件
     * 进行列表过滤
     *
     * 过滤条件
     * $map['_table']       可强制设置表名前缀
     * $map['_relation']    可强制设置关联模型预载入(需在模型里定义)
     * $map['_field']       可强制设置字段
     * $map['_order_by']    可强制设置排序字段(field asc|desc[,filed2 asc|desc...]或者false)
     * $map['_paginate']    是否开启分页,传入false可以关闭分页
     * $map['_model']       可强制指定模型
     * $map['_func']        匿名函数,可以给模型设置属性,比如关联,alias,function ($model) {$model->alias('table')->join(...)}
     *
     * @param Model|Db $model    数据对象
     * @param array    $map      过滤条件
     * @param string   $field    查询的字段
     * @param string   $sortBy   排序
     * @param boolean  $asc      是否正序
     * @param boolean  $return   是否返回数据,返回数据时返回paginate对象,不返回时直接模板赋值
     * @param boolean  $paginate 是否开启分页
     */
    protected function datalist($model, $map, $field = null, $sortBy = '', $asc = false, $return = false, $paginate = true)
    {
        // 私有字段,指定特殊条件,查询时要删除
        $protectField = ['_table', '_relation', '_field', '_order_by', '_paginate', '_model', '_func'];

        // 通过过滤器指定模型
        if (isset($map['_model'])) {
            $model = $map['_model'];
        }

        if (isset($map['_func']) && ($map['_func'] instanceof \Closure)) {
            call_user_func_array($map['_func'], [$model]);
        }

        // 排序字段 默认为主键名
        $order = $this->request->param('_order') ?: (empty($sortBy) ? $model->getPk() : $sortBy);

        // 接受 sort参数 0 表示倒序 非0都 表示正序
        $sort = null !== $this->request->param('_sort')
            ? ($this->request->param('_sort') == 'asc' ? 'asc' : 'desc')
            : ($asc ? 'asc' : 'desc');

        // 设置关联预载入
        if (isset($map['_relation'])) {
            $model = $model::with($map['_relation']);
        }

        // 设置字段
        if (isset($map['_field'])) {
            $field = $map['_field'];
        }

        // 设置有$map['_controller']表示存在关联模型
        if (isset($map['_table'])) {
            // 给排序字段强制加上表名前缀
            if (strpos($order, ".") === false) {
                $order = $map['_table'] . "." . $order;
            }
            // 给字段强制加上表名前缀
            $_field = is_array($field) ? $field : explode(",", $field);
            foreach ($_field as &$v) {
                if (strpos($v, ".") === false) {
                    $v = preg_replace("/([^\s\(\)]*[a-z0-9\*])/", $map['_table'] . '.$1', $v, 1);
                }
            }
            $field = implode(",", $_field);
            // 给查询条件强制加上表名前缀
            foreach ($map as $k => $v) {
                if (!in_array($k, $protectField) && strpos($k, ".") === false) {
                    $map[$map['_table'] . '.' . $k] = $v;
                    unset($map[$k]);
                }
            }
        }

        // 设置排序字段 防止表无主键报错
        $order_by = $order ? "{$order} {$sort}" : false;
        if (isset($map['_order_by'])) {
            $order_by = $map['_order_by'];
        }

        // 是否开启分页
        $paginate = isset($map['_paginate']) ? boolval($map['_paginate']) : $paginate;

        // 删除设置属性的字段
        foreach ($protectField as $v) {
            unset($map[$v]);
        }

        if ($paginate) {
            // 分页查询

            // 每页数据数量
            $listRows = $this->request->param('numPerPage') ?: Config::get("paginate.list_rows");

            $list = $model
                ->field($field)
                ->where($map)
                ->order($order_by)
                ->paginate($listRows, false, ['query' => $this->request->get()]);

            if ($return) {
                // 返回值
                return $list;
            } else {
                // 模板赋值显示
                $this->view->assign('list', $list);
                $this->view->assign("count", $list->total());
                $this->view->assign("page", $list->render());
                $this->view->assign('numPerPage', $list->listRows());
            }
        } else {
            // 不开启分页查询
            $list = $model
                ->field($field)
                ->where($map)
                ->order($order_by)
                ->select();

            if ($return) {
                // 返回值
                return $list;
            } else {
                // 模板赋值显示
                $this->view->assign('list', $list);
                $this->view->assign("count", count($list));
                $this->view->assign("page", '');
                $this->view->assign('numPerPage', 0);
            }
        }
    }

    /**
     * 将abc.def.Gh转为AbcDefGh
     *
     * @param $string
     *
     * @return mixed
     */
    protected function parseCamelCase($string)
    {
        return preg_replace_callback('/(\.|^)([a-zA-Z])/', function ($match) {
            return ucfirst($match[2]);
        }, $string);
    }
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

“ViooMa进销存|ViooMa收银系统”是采用ThinkPHP框架开发(PHP+Mysql语言编写)的PHP Web进销存系统|PHP收银系统,是一套集进、销、存和简单财务管理于一体的WEB进销存及收银管理软件,本收银系统集微信和支付宝及网络语音打印机自助接单,深受广大中小企业欢迎,该软件采用独特的算法和操作理念设计,简单易用,就算是不懂电脑的人也能很容易上手。 ViooMa进销存系统-进销存与往来帐务实现一体化,大量重复烦琐的工作均由web进销存系统自动完成,操作过程简化,大大降低使用人员的工作量。只需简单地录入进货、销售、收款、付款等单据,而系统就自动帮您统计、分析、分类、汇总各类单据信息生成相应的报表。此外,还可随时查询和分析进货、销售、库存、应收、应付、成本、利润等信息,以及随时与每一位供应商和客户进行清晰、快速地往来对帐,让您能及时、清晰地掌握公司每天的经营状况。   产品特点:   功能简洁实用,操作简便 前台收银系统支持微信和支付宝扫码支付 集成飞鹅网络语音热敏小票打印机接口 含丰富的图表和数据统计报表,轻松掌握店铺动作和账务情况 采用ThinkPHP框架开发,代码完全开源,方便二次开发 我们提供系统全方位定制服务,助你完成适合自己企业的系统   多个功能浓缩或聚集在一起,让您不用“团团转”,更加不会眼花缭乱,做到一目了然。   易学易用,就算没有特别计算机知识的人,在极短的时间内便可掌握并熟悉整个系统的操作 和流程,麻雀虽小,却五脏俱全,此软件适用于一般商贸业务管理活动。   强大数据存储能力与反映速度;   本系统采用PHP+Mysql环境开发,拥有强大的数据存储能力和反映速度,较一般的进销存有着更大的优势,同时界面人性化处理,操作极其顺手,是你管理不可少的好软件。   安装说明:   安装要求(PHP环境+Mysql环境)   1、解压所下载的文件至本地,把vioomajxc目录下文件上传至你的服务器。   2、执行安装文件如下:http://www.yourweb.com/install 或 http://www.yourweb.com/子目录/install   3、安装前请确保相关目录有写入权限,然后根据提示设定好相关参数,直到安装完成即可。   4、安装完成后,把public/install目录删除,删除前请做好备份,以便需要时进行安装。   5、ViooMa进销存系统需要服务器支持rewrite,不会设置的可以直接导入根目录下的.htaccess文件到IIS。
小型超市进销管理系统(SCDN)是一种专门为小型超市设计的进销存管理软件。它旨在帮助小型超市高效地管理商品进销和库存情况,提高销售业绩和盈利能力。 SCDN系统具有以下主要功能: 1. 商品管理:用户可以通过系统对商品进行录入、修改和删除,包括商品名称、价格、库存量等相关信息。同时,系统还支持查看商品销售统计和库存预警功能,及时补充库存并避免货物积压。 2. 进销管理:系统可以实时记录商品的采购和销售情况,包括供应商信息、进货单、销售单等。用户可以方便地查询特定时间段内的进销情况,分析销售数据,制定合理的采购和促销策略,提高销售效益。 3. 会员管理:系统支持会员管理功能,用户可以录入、修改和删除会员信息,包括会员等级、消费积分等。通过会员积分的积累和兑换,可以提高会员的粘性和忠诚度,增加重复消费。 4. 库存管理:系统可实时监控商品的库存情况,包括库存数量、库存成本等。当库存达到设定的预警值时,系统会自动提醒用户及时补充货物,避免因库存不足导致的销售中断和客户流失。 5. 报表分析:系统提供各类报表和数据分析功能,如销售报表、进货报表、会员消费报表等。用户可以根据报表分析销售趋势,调整经营策略,提高超市的经营效率和盈利水平。 总之,小型超市进销管理系统(SCDN)通过提供全面的进销存管理功能,帮助超市管理者更好地掌握商品的销售和库存情况,优化经营决策,提升超市运营效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值