Compare commits

..

14 Commits

Author SHA1 Message Date
root
537d81beb1 优化登录页:标题完整显示+渐变色设计
All checks were successful
continuous-integration/drone/push Build is passing
2026-02-15 14:10:50 +01:00
root
25c4bf7ad1 rebrand: rename to MileStone Co. ERP
All checks were successful
continuous-integration/drone/push Build is passing
2026-02-15 13:31:44 +01:00
root
3e88e757a8 Switch to Docker pipeline for Drone CI 2026-02-14 19:24:12 +01:00
root
e5ac5fa492 Add Dockerfile, Drone CI config, fix main class 2026-02-14 19:23:34 +01:00
jishenghua
66d3ffd0d0 在销售订单的单据查看页面,给明细增加已销售的金额合计 2026-02-11 17:07:48 +08:00
jishenghua
547660462b 给销售订单加上结算账户的查询条件 2026-02-11 16:57:45 +08:00
jishenghua
0d49485cf9 完善重置密码的功能,增加页面 2026-02-05 21:21:31 +08:00
jishenghua
928178bc1f 完善重置密码的功能,增加页面 2026-02-05 21:18:40 +08:00
jishenghua
e4c6207fa7 给用户的录入界面增加密码的输入 2026-02-05 18:23:42 +08:00
jishenghua
5768ca646e 修复bug:比如只给租户角色的菜单里面的基础资料赋予供应商的菜单,然后用租户去登录,再去给下级用户赋予菜单的时候,发现没有基础资料这个大菜单 2026-02-05 12:31:17 +08:00
jishenghua
6be053a5c1 修复bug:解决用户管理中不选择机构就不能排序的问题 2026-01-31 14:27:07 +08:00
jishenghua
43d50cdaf0 给商品多属性选择的时候的多余的判断提示 2026-01-30 16:50:49 +08:00
jishenghua
9990a3c4f3 为排序字段添加白名单验证 2026-01-30 11:52:37 +08:00
jishenghua
1065be3c47 为排序字段添加白名单验证 2026-01-30 11:44:08 +08:00
25 changed files with 369 additions and 145 deletions

45
.drone.yml Normal file
View File

@@ -0,0 +1,45 @@
kind: pipeline
type: docker
name: build-and-deploy
steps:
- name: build-backend
image: maven:3.9-amazoncorretto-8
commands:
- cd jshERP-boot
- mvn package -DskipTests
volumes:
- name: maven-cache
path: /root/.m2
- name: build-frontend
image: node:18-alpine
commands:
- cd jshERP-web
- npm install --legacy-peer-deps
- npx vue-cli-service build
- name: docker-build-deploy
image: docker:dind
volumes:
- name: docker-sock
path: /var/run/docker.sock
commands:
- docker build -t jsherp:latest .
- docker stop jsherp || true
- docker rm jsherp || true
- docker run -d --name jsherp --network host -v /opt/jshERP/upload:/opt/jshERP/upload --restart unless-stopped jsherp:latest
volumes:
- name: maven-cache
host:
path: /root/.m2
- name: docker-sock
host:
path: /var/run/docker.sock
trigger:
branch:
- master
event:
- push

8
Dockerfile Normal file
View File

@@ -0,0 +1,8 @@
FROM amazoncorretto:8-alpine
RUN apk add --no-cache fontconfig ttf-dejavu
WORKDIR /app
COPY jshERP-boot/target/jshERP.jar /app/jshERP.jar
COPY jshERP-web/dist /app/static
RUN mkdir -p /opt/jshERP/upload /opt/tmp/tomcat
EXPOSE 9999
ENTRYPOINT ["java", "-jar", "/app/jshERP.jar"]

View File

@@ -580,7 +580,7 @@ INSERT INTO `jsh_msg` VALUES (2, '标题1', '内容1', '2019-09-10 00:11:39', '
DROP TABLE IF EXISTS `jsh_orga_user_rel`; DROP TABLE IF EXISTS `jsh_orga_user_rel`;
CREATE TABLE `jsh_orga_user_rel` ( CREATE TABLE `jsh_orga_user_rel` (
`id` bigint(0) NOT NULL AUTO_INCREMENT COMMENT '主键', `id` bigint(0) NOT NULL AUTO_INCREMENT COMMENT '主键',
`orga_id` bigint(0) NOT NULL COMMENT '机构id', `orga_id` bigint(0) NULL DEFAULT NULL COMMENT '机构id',
`user_id` bigint(0) NOT NULL COMMENT '用户id', `user_id` bigint(0) NOT NULL COMMENT '用户id',
`user_blng_orga_dspl_seq` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '用户在所属机构中显示顺序', `user_blng_orga_dspl_seq` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '用户在所属机构中显示顺序',
`delete_flag` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '0' COMMENT '删除标记0未删除1删除', `delete_flag` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '0' COMMENT '删除标记0未删除1删除',

View File

@@ -1745,3 +1745,10 @@ create index depot_id on jsh_serial_number(depot_id) using btree;
create index type on jsh_user_business(type) using btree; create index type on jsh_user_business(type) using btree;
create index key_id on jsh_user_business(key_id) using btree; create index key_id on jsh_user_business(key_id) using btree;
create index tenant_id on jsh_user_business(tenant_id) using btree; create index tenant_id on jsh_user_business(tenant_id) using btree;
-- --------------------------------------------------------
-- 时间 2026年1月31日
-- by jishenghua
-- 给jsh_user表的orga_id字段改为非必填
-- --------------------------------------------------------
alter table jsh_orga_user_rel change orga_id orga_id bigint(0) NULL DEFAULT NULL COMMENT '机构id';

View File

@@ -141,6 +141,9 @@
<plugin> <plugin>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId> <artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>com.jsh.erp.ErpApplication</mainClass>
</configuration>
<version>2.0.3.RELEASE</version> <version>2.0.3.RELEASE</version>
<executions> <executions>
<execution> <execution>

View File

@@ -215,6 +215,7 @@ public class DepotItemController {
BigDecimal totalAllPrice = BigDecimal.ZERO; BigDecimal totalAllPrice = BigDecimal.ZERO;
BigDecimal totalTaxMoney = BigDecimal.ZERO; BigDecimal totalTaxMoney = BigDecimal.ZERO;
BigDecimal totalTaxLastMoney = BigDecimal.ZERO; BigDecimal totalTaxLastMoney = BigDecimal.ZERO;
BigDecimal totalFinishNumber = BigDecimal.ZERO;
BigDecimal totalWeight = BigDecimal.ZERO; BigDecimal totalWeight = BigDecimal.ZERO;
for (DepotItemVo4WithInfoEx diEx : dataList) { for (DepotItemVo4WithInfoEx diEx : dataList) {
JSONObject item = new JSONObject(); JSONObject item = new JSONObject();
@@ -252,7 +253,8 @@ public class DepotItemController {
item.put("operNumber", diEx.getOperNumber()); item.put("operNumber", diEx.getOperNumber());
item.put("basicNumber", diEx.getBasicNumber()); item.put("basicNumber", diEx.getBasicNumber());
item.put("preNumber", diEx.getOperNumber()); //原数量 item.put("preNumber", diEx.getOperNumber()); //原数量
item.put("finishNumber", depotItemService.getFinishNumber(diEx.getMaterialExtendId(), diEx.getId(), diEx.getHeaderId(), unitInfo, materialUnit, linkType)); //已入库|已出库 BigDecimal finishNumber = depotItemService.getFinishNumber(diEx.getMaterialExtendId(), diEx.getId(), diEx.getHeaderId(), unitInfo, materialUnit, linkType);
item.put("finishNumber", finishNumber); //已入库|已出库
item.put("purchaseDecimal", roleService.parseBillPriceByLimit(diEx.getPurchaseDecimal(), billCategory, priceLimit, request)); //采购价 item.put("purchaseDecimal", roleService.parseBillPriceByLimit(diEx.getPurchaseDecimal(), billCategory, priceLimit, request)); //采购价
if("basic".equals(linkType) || "1".equals(isReadOnly)) { if("basic".equals(linkType) || "1".equals(isReadOnly)) {
//正常情况显示金额,而以销定购的情况不能显示金额 //正常情况显示金额,而以销定购的情况不能显示金额
@@ -288,6 +290,7 @@ public class DepotItemController {
totalAllPrice = totalAllPrice.add(diEx.getAllPrice()==null?BigDecimal.ZERO:diEx.getAllPrice()); totalAllPrice = totalAllPrice.add(diEx.getAllPrice()==null?BigDecimal.ZERO:diEx.getAllPrice());
totalTaxMoney = totalTaxMoney.add(diEx.getTaxMoney()==null?BigDecimal.ZERO:diEx.getTaxMoney()); totalTaxMoney = totalTaxMoney.add(diEx.getTaxMoney()==null?BigDecimal.ZERO:diEx.getTaxMoney());
totalTaxLastMoney = totalTaxLastMoney.add(diEx.getTaxLastMoney()==null?BigDecimal.ZERO:diEx.getTaxLastMoney()); totalTaxLastMoney = totalTaxLastMoney.add(diEx.getTaxLastMoney()==null?BigDecimal.ZERO:diEx.getTaxLastMoney());
totalFinishNumber = totalFinishNumber.add(finishNumber);
totalWeight = totalWeight.add(allWeight); totalWeight = totalWeight.add(allWeight);
} }
if(StringUtil.isNotEmpty(isReadOnly) && "1".equals(isReadOnly)) { if(StringUtil.isNotEmpty(isReadOnly) && "1".equals(isReadOnly)) {
@@ -296,6 +299,7 @@ public class DepotItemController {
footItem.put("allPrice", roleService.parseBillPriceByLimit(totalAllPrice, billCategory, priceLimit, request)); footItem.put("allPrice", roleService.parseBillPriceByLimit(totalAllPrice, billCategory, priceLimit, request));
footItem.put("taxMoney", roleService.parseBillPriceByLimit(totalTaxMoney, billCategory, priceLimit, request)); footItem.put("taxMoney", roleService.parseBillPriceByLimit(totalTaxMoney, billCategory, priceLimit, request));
footItem.put("taxLastMoney", roleService.parseBillPriceByLimit(totalTaxLastMoney, billCategory, priceLimit, request)); footItem.put("taxLastMoney", roleService.parseBillPriceByLimit(totalTaxLastMoney, billCategory, priceLimit, request));
footItem.put("finishNumber", totalFinishNumber);
footItem.put("weight", totalWeight); footItem.put("weight", totalWeight);
dataArray.add(footItem); dataArray.add(footItem);
} }

View File

@@ -241,7 +241,7 @@ public class FunctionController extends BaseController {
if("admin".equals(userInfo.getLoginName())) { if("admin".equals(userInfo.getLoginName())) {
funIdList = null; funIdList = null;
} }
List<Function> dataListFun = functionService.findRoleFunction("0", funIdList); List<Function> dataListFun = functionService.findRoleFunction("0", null);
//开始拼接json数据 //开始拼接json数据
JSONObject outer = new JSONObject(); JSONObject outer = new JSONObject();
outer.put("id", 0); outer.put("id", 0);
@@ -255,15 +255,20 @@ public class FunctionController extends BaseController {
//根据条件从列表里面移除"系统管理" //根据条件从列表里面移除"系统管理"
List<Function> dataList = new ArrayList<>(); List<Function> dataList = new ArrayList<>();
for (Function fun : dataListFun) { for (Function fun : dataListFun) {
List<Function> childrenList = functionService.getRoleFunction(fun.getNumber());
String token = request.getHeader("X-Access-Token"); String token = request.getHeader("X-Access-Token");
Long tenantId = Tools.getTenantIdByToken(token); Long tenantId = Tools.getTenantIdByToken(token);
if (tenantId!=0L) { if (tenantId!=0L) {
if(!("系统管理").equals(fun.getName())) { if(!("系统管理").equals(fun.getName())) {
dataList.add(fun); if(!childrenList.isEmpty()) {
dataList.add(fun);
}
} }
} else { } else {
//超管 //超管
dataList.add(fun); if(!childrenList.isEmpty()) {
dataList.add(fun);
}
} }
} }
dataArray = getFunctionList(dataList, type, keyId, funIdList); dataArray = getFunctionList(dataList, type, keyId, funIdList);

View File

@@ -233,8 +233,7 @@ public class UserController extends BaseController {
HttpServletRequest request) throws Exception { HttpServletRequest request) throws Exception {
Map<String, Object> objectMap = new HashMap<>(); Map<String, Object> objectMap = new HashMap<>();
Long id = jsonObject.getLong("id"); Long id = jsonObject.getLong("id");
String password = "123456"; String md5Pwd = jsonObject.getString("password");
String md5Pwd = Tools.md5Encryp(password);
int update = userService.resetPwd(md5Pwd, id, request); int update = userService.resetPwd(md5Pwd, id, request);
if(update > 0) { if(update > 0) {
return returnJson(objectMap, SUCCESS, ErpInfo.OK.code); return returnJson(objectMap, SUCCESS, ErpInfo.OK.code);

View File

@@ -553,10 +553,6 @@ public class UserService {
ubObj.put("value", "[" + ue.getRoleId() + "]"); ubObj.put("value", "[" + ue.getRoleId() + "]");
userBusinessService.insertUserBusiness(ubObj, request); userBusinessService.insertUserBusiness(ubObj, request);
} }
if(ue.getOrgaId()==null){
//如果没有选择机构,就不建机构和用户的关联关系
return;
}
if(ue.getOrgaId()!=null && "1".equals(ue.getLeaderFlag())){ if(ue.getOrgaId()!=null && "1".equals(ue.getLeaderFlag())){
//检查当前机构是否存在经理 //检查当前机构是否存在经理
List<User> checkList = userMapperEx.getListByOrgaId(ue.getId(), ue.getOrgaId()); List<User> checkList = userMapperEx.getListByOrgaId(ue.getId(), ue.getOrgaId());
@@ -585,12 +581,10 @@ public class UserService {
public UserEx addUser(UserEx ue) throws Exception{ public UserEx addUser(UserEx ue) throws Exception{
/** /**
* 新增用户默认设置 * 新增用户默认设置
* 1、密码默认123456 * 1是否系统自带默认为非系统自带
* 2是否系统自带默认为非系统自带 * 2是否管理者默认为员工
* 3是否管理者默认为员工 * 3默认用户状态为正常
* 4默认用户状态为正常
* */ * */
ue.setPassword(Tools.md5Encryp(BusinessConstants.USER_DEFAULT_PASSWORD));
ue.setIsystem(BusinessConstants.USER_NOT_SYSTEM); ue.setIsystem(BusinessConstants.USER_NOT_SYSTEM);
if(ue.getIsmanager()==null){ if(ue.getIsmanager()==null){
ue.setIsmanager(BusinessConstants.USER_NOT_MANAGER); ue.setIsmanager(BusinessConstants.USER_NOT_MANAGER);
@@ -707,10 +701,6 @@ public class UserService {
userBusinessService.insertUserBusiness(ubObj, request); userBusinessService.insertUserBusiness(ubObj, request);
} }
} }
if (ue.getOrgaId() == null) {
//如果没有选择机构,就不建机构和用户的关联关系
return;
}
if(ue.getOrgaId()!=null && "1".equals(ue.getLeaderFlag())){ if(ue.getOrgaId()!=null && "1".equals(ue.getLeaderFlag())){
//检查当前机构是否存在经理 //检查当前机构是否存在经理
List<User> checkList = userMapperEx.getListByOrgaId(ue.getId(), ue.getOrgaId()); List<User> checkList = userMapperEx.getListByOrgaId(ue.getId(), ue.getOrgaId());

View File

@@ -7,13 +7,13 @@ server.servlet.context-path=/jshERP-boot
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/jsh_erp?useUnicode=true&characterEncoding=utf8&useCursorFetch=true&defaultFetchSize=500&allowMultiQueries=true&rewriteBatchedStatements=true&useSSL=false spring.datasource.url=jdbc:mysql://127.0.0.1:3306/jsh_erp?useUnicode=true&characterEncoding=utf8&useCursorFetch=true&defaultFetchSize=500&allowMultiQueries=true&rewriteBatchedStatements=true&useSSL=false
spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver
spring.datasource.username=root spring.datasource.username=root
spring.datasource.password=123456 spring.datasource.password=Qweewqzzx1
#mybatis-plus配置 #mybatis-plus配置
mybatis-plus.mapper-locations=classpath:./mapper_xml/*.xml mybatis-plus.mapper-locations=classpath:./mapper_xml/*.xml
# Redis # Redis
spring.redis.host=127.0.0.1 spring.redis.host=127.0.0.1
spring.redis.port=6379 spring.redis.port=6379
spring.redis.password=1234abcd spring.redis.password=
#租户对应的角色id #租户对应的角色id
manage.roleId=10 manage.roleId=10
#租户允许创建的用户数 #租户允许创建的用户数

View File

@@ -276,7 +276,12 @@
order by oper_time desc,number desc order by oper_time desc,number desc
</if> </if>
<if test="column != 'createTime'"> <if test="column != 'createTime'">
order by ${column} ${order} <if test="column == 'barCode' or column == 'operNumber' or column == 'unitPrice' or column == 'allPrice' or column == 'taxMoney'">
order by ${column}
<if test="order == 'asc' or order == 'desc'">
${order}
</if>
</if>
</if> </if>
<if test="offset != null and rows != null"> <if test="offset != null and rows != null">
limit #{offset},#{rows} limit #{offset},#{rows}
@@ -495,7 +500,12 @@
order by materialId desc order by materialId desc
</if> </if>
<if test="column != 'createTime'"> <if test="column != 'createTime'">
order by ${column} ${order} <if test="column == 'barCode' or column == 'numSum' or column == 'priceSum'">
order by ${column}
<if test="order == 'asc' or order == 'desc'">
${order}
</if>
</if>
</if> </if>
<if test="offset != null and rows != null"> <if test="offset != null and rows != null">
limit #{offset},#{rows} limit #{offset},#{rows}
@@ -701,7 +711,12 @@
order by oper_time desc,number desc order by oper_time desc,number desc
</if> </if>
<if test="column != 'createTime'"> <if test="column != 'createTime'">
order by ${column} ${order} <if test="column == 'barCode' or column == 'operNumber' or column == 'unitPrice' or column == 'allPrice'">
order by ${column}
<if test="order == 'asc' or order == 'desc'">
${order}
</if>
</if>
</if> </if>
<if test="offset != null and rows != null"> <if test="offset != null and rows != null">
limit #{offset},#{rows} limit #{offset},#{rows}

View File

@@ -698,7 +698,12 @@
order by m.id desc order by m.id desc
</if> </if>
<if test="column != 'createTime'"> <if test="column != 'createTime'">
order by ${column} ${order} <if test="column == 'mBarCode' or column == 'purchaseDecimal' or column == 'currentStock' or column == 'currentStockPrice' or column == 'currentWeight'">
order by ${column}
<if test="order == 'asc' or order == 'desc'">
${order}
</if>
</if>
</if> </if>
<if test="offset != null and rows != null"> <if test="offset != null and rows != null">
limit #{offset},#{rows} limit #{offset},#{rows}

View File

@@ -17,9 +17,7 @@
<update id="updateOrgaUserRel" parameterType="com.jsh.erp.datasource.entities.OrgaUserRel" > <update id="updateOrgaUserRel" parameterType="com.jsh.erp.datasource.entities.OrgaUserRel" >
update jsh_orga_user_rel update jsh_orga_user_rel
<set > <set >
<if test="orgaId != null" > orga_id = #{orgaId},
orga_id = #{orgaId},
</if>
<if test="userId != null" > <if test="userId != null" >
user_id = #{userId}, user_id = #{userId},
</if> </if>

View File

@@ -5,7 +5,7 @@
<meta charset="utf-8"> <meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0"> <meta name="viewport" content="width=device-width,initial-scale=1.0">
<meta name="description" content="基于SpringBoot框架立志为中小企业提供开源好用的ERP软件目前专注进销存+财务功能。主要模块有零售管理、采购管理、销售管理、仓库管理、财务管理、报表查询、基础数据、系统管理等。" /> <meta name="description" content="MileStone Industrial Development Corporation ERP System" />
<meta name="keywords" content="erp,erp系统,进销存,进销存系统" /> <meta name="keywords" content="erp,erp系统,进销存,进销存系统" />
<link rel="icon" href="<%= BASE_URL %>static/favicon.ico"> <link rel="icon" href="<%= BASE_URL %>static/favicon.ico">
<style> <style>
@@ -248,7 +248,7 @@
if (ajax.readyState===4 &&ajax.status===200) { if (ajax.readyState===4 &&ajax.status===200) {
res = ajax.responseText; res = ajax.responseText;
} else { } else {
res = 'ERP系统'; res = 'MileStone Co. ERP';
} }
} }
ajax.open('get', url, false); ajax.open('get', url, false);
@@ -295,7 +295,7 @@ translate.language.setLocal('chinese_simplified');
translate.service.use('client.edge'); translate.service.use('client.edge');
//翻译自定义 //翻译自定义
translate.nomenclature.append('chinese_simplified','english',` translate.nomenclature.append('chinese_simplified','english',`
管伊佳ERP=GuanYiJia MileStone Co. ERP=MileStone Co. ERP
`) `)
//开启html页面变化的监控对变化部分会进行自动翻译 //开启html页面变化的监控对变化部分会进行自动翻译
translate.listener.start(); translate.listener.start();

View File

@@ -20,6 +20,7 @@ const editUser = (params)=>putAction("/user/updateUser",params);
const getUserList = (params)=>getAction("/user/getUserList",params); const getUserList = (params)=>getAction("/user/getUserList",params);
const getUserBtnByCurrentUser = (params)=>getAction("/user/getUserBtnByCurrentUser",params); const getUserBtnByCurrentUser = (params)=>getAction("/user/getUserBtnByCurrentUser",params);
const queryPermissionsByUser = (params)=>postAction("/function/findMenuByPNumber",params); const queryPermissionsByUser = (params)=>postAction("/function/findMenuByPNumber",params);
const resetPwd = (params)=>postAction("/user/resetPwd",params);
//机构管理 //机构管理
const queryOrganizationTreeList = (params)=>getAction("/organization/getOrganizationTree",params); const queryOrganizationTreeList = (params)=>getAction("/organization/getOrganizationTree",params);
const getAllOrganizationTreeByUser = (params)=>getAction("/organization/getAllOrganizationTreeByUser",params); const getAllOrganizationTreeByUser = (params)=>getAction("/organization/getAllOrganizationTreeByUser",params);
@@ -131,6 +132,7 @@ export {
getUserList, getUserList,
getUserBtnByCurrentUser, getUserBtnByCurrentUser,
queryPermissionsByUser, queryPermissionsByUser,
resetPwd,
queryOrganizationTreeList, queryOrganizationTreeList,
getAllOrganizationTreeByUser, getAllOrganizationTreeByUser,
queryOrganizationById, queryOrganizationById,

View File

@@ -193,7 +193,7 @@
background-size: 100%; background-size: 100%;
position: relative; position: relative;
width: 340px; width: 340px;
height: 460px; height: 500px;
background: rgba(255, 255, 255, 1); background: rgba(255, 255, 255, 1);
border-radius: 8px; border-radius: 8px;
right: 0; right: 0;
@@ -212,24 +212,28 @@
text-align: center; text-align: center;
.header { .header {
height: 44px; height: auto;
line-height: 44px; line-height: 1.3;
margin-top: 35px; margin-top: 30px;
margin-bottom: 35px; margin-bottom: 30px;
text-align: center;
.title { .title {
font-size: 35px; font-size: 28px;
color: #666; background: linear-gradient(135deg, #1890ff, #722ed1);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
font-family: "Chinese Quote", -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; font-family: "Chinese Quote", -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
font-weight: 700; font-weight: 700;
position: relative; letter-spacing: 1px;
top: 2px; display: inline;
} }
.desc { .desc {
font-size: 16px; font-size: 14px;
color: #666; color: #999;
margin-top: 12px; margin-top: 4px;
margin-left: 10px; margin-left: 8px;
margin-bottom: 40px; display: inline;
} }
} }
} }

View File

@@ -3,7 +3,7 @@
<span class="action" v-if="showAd"> <span class="action" v-if="showAd">
<a v-if="theme==='light'" class="ad_title" target="_blank" :href="payFeeUrl"> <a v-if="theme==='light'" class="ad_title" target="_blank" :href="payFeeUrl">
<a-icon type="cloud" theme="filled" style="color: yellow; font-size: 16px; line-height: 16px; padding-right: 5px" /> <a-icon type="cloud" theme="filled" style="color: yellow; font-size: 16px; line-height: 16px; padding-right: 5px" />
<span>管伊佳ERP网络版198元1年</span> <span>MileStone Co. ERP</span>
</a> </a>
</span> </span>
<!-- update_begin author:zhaoxin date:20191129 for: 做头部菜单栏导航 --> <!-- update_begin author:zhaoxin date:20191129 for: 做头部菜单栏导航 -->

View File

@@ -133,7 +133,7 @@
} }
let reg = /^(?=.*[a-z])(?=.*\d).{6,}$/; let reg = /^(?=.*[a-z])(?=.*\d).{6,}$/;
if (!reg.test(value)) { if (!reg.test(value)) {
callback(new Error('密码由6位数字小写字母组成!')) callback(new Error('用户密码至少要有数字和小写字母并且长度至少6位!'))
} }
callback() callback()
}, },

View File

@@ -75,6 +75,15 @@
<a-input placeholder="请输入关联订单" v-model="queryParam.linkNumber"></a-input> <a-input placeholder="请输入关联订单" v-model="queryParam.linkNumber"></a-input>
</a-form-item> </a-form-item>
</a-col> </a-col>
<a-col :md="6" :sm="24">
<a-form-item label="结算账户" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-select placeholder="请选择结算账户" showSearch allow-clear optionFilterProp="children" v-model="queryParam.accountId">
<a-select-option v-for="(item,index) in accountList" :key="index" :value="item.id">
{{ item.name }}
</a-select-option>
</a-select>
</a-form-item>
</a-col>
<a-col :md="6" :sm="24"> <a-col :md="6" :sm="24">
<a-form-item label="单据状态" :labelCol="labelCol" :wrapperCol="wrapperCol"> <a-form-item label="单据状态" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-select placeholder="请选择单据状态" allow-clear v-model="queryParam.status"> <a-select placeholder="请选择单据状态" allow-clear v-model="queryParam.status">
@@ -235,6 +244,7 @@
depotId: undefined, depotId: undefined,
linkApply: "", linkApply: "",
linkNumber: "", linkNumber: "",
accountId: undefined,
creator: undefined, creator: undefined,
status: undefined, status: undefined,
remark: "" remark: ""
@@ -310,6 +320,7 @@
this.initSystemConfig() this.initSystemConfig()
this.initSupplier() this.initSupplier()
this.initUser() this.initUser()
this.initAccount()
this.initQuickBtn() this.initQuickBtn()
this.getDepotByCurrentUser() this.getDepotByCurrentUser()
}, },

View File

@@ -66,6 +66,15 @@
</a-select> </a-select>
</a-form-item> </a-form-item>
</a-col> </a-col>
<a-col :md="6" :sm="24">
<a-form-item label="结算账户" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-select placeholder="请选择结算账户" showSearch allow-clear optionFilterProp="children" v-model="queryParam.accountId">
<a-select-option v-for="(item,index) in accountList" :key="index" :value="item.id">
{{ item.name }}
</a-select-option>
</a-select>
</a-form-item>
</a-col>
<a-col :md="6" :sm="24"> <a-col :md="6" :sm="24">
<a-form-item label="单据状态" :labelCol="labelCol" :wrapperCol="wrapperCol"> <a-form-item label="单据状态" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-select placeholder="请选择单据状态" allow-clear v-model="queryParam.status"> <a-select placeholder="请选择单据状态" allow-clear v-model="queryParam.status">
@@ -240,6 +249,7 @@
subType: "销售订单", subType: "销售订单",
organId: undefined, organId: undefined,
depotId: undefined, depotId: undefined,
accountId: undefined,
creator: undefined, creator: undefined,
status: undefined, status: undefined,
salesMan: undefined, salesMan: undefined,
@@ -316,6 +326,7 @@
this.initCustomer() this.initCustomer()
this.initSalesman() this.initSalesman()
this.initUser() this.initUser()
this.initAccount()
this.getSystemConfig() this.getSystemConfig()
this.initQuickBtn() this.initQuickBtn()
this.getDepotByCurrentUser() this.getDepotByCurrentUser()

View File

@@ -131,7 +131,7 @@
<div slot="content"> <div slot="content">
<img src="/static/weixin.jpg" style="width:258px" /> <img src="/static/weixin.jpg" style="width:258px" />
</div> </div>
<a-button type="link" v-if="showWeixinSpan()">管伊佳ERP微信小程序</a-button> <a-button type="link" v-if="showWeixinSpan()">MileStone Co. ERP</a-button>
</a-popover> </a-popover>
&copy; 2015-2030 {{systemTitle}} V3.6 &copy; 2015-2030 {{systemTitle}} V3.6
</div> </div>

View File

@@ -980,90 +980,85 @@
}, },
autoSkuList(skuOneData, skuTwoData, skuThreeData) { autoSkuList(skuOneData, skuTwoData, skuThreeData) {
let unit = this.form.getFieldValue('unit') let unit = this.form.getFieldValue('unit')
if(unit) { //计算多属性已经选择了几个
//计算多属性已经选择了几个 let skuArr = []
let skuArr = [] if(this.getNumByField('skuOne')) {
if(this.getNumByField('skuOne')) { skuArr.push(skuOneData)
skuArr.push(skuOneData)
}
if(this.getNumByField('skuTwo')) {
skuArr.push(skuTwoData)
}
if(this.getNumByField('skuThree')) {
skuArr.push(skuThreeData)
}
let skuArrOne = skuArr[0]
let skuArrTwo = skuArr[1]
let skuArrThree = skuArr[2]
let count = this.getNumByField('skuOne') + this.getNumByField('skuTwo') + this.getNumByField('skuThree')
let barCodeSku = []
if(count === 1) {
let skuArrOnly = []
if(this.getNumByField('skuOne')) {
skuArrOnly = skuOneData
} else if(this.getNumByField('skuTwo')) {
skuArrOnly = skuTwoData
} else if(this.getNumByField('skuThree')) {
skuArrOnly = skuThreeData
}
for (let i = 0; i < skuArrOnly.length; i++) {
barCodeSku.push(skuArrOnly[i])
}
} else if(count === 2) {
for (let i = 0; i < skuArrOne.length; i++) {
for (let j = 0; j < skuArrTwo.length; j++) {
barCodeSku.push(skuArrOne[i] + '/' + skuArrTwo[j])
}
}
} else if(count === 3) {
for (let i = 0; i < skuArrOne.length; i++) {
for (let j = 0; j < skuArrTwo.length; j++) {
for (let k = 0; k < skuArrThree.length; k++) {
barCodeSku.push(skuArrOne[i] + '/' + skuArrTwo[j] + '/' + skuArrThree[k])
}
}
}
}
let meTableData = []
getMaxBarCode({}).then((res)=>{
if(res && res.code===200) {
let k = 0
let maxBarCode = res.data.barCode
for (let i = 0; i < barCodeSku.length; i++) {
let currentBarCode = ''
let currentId = ''
let purchaseDecimal = ''
let commodityDecimal = ''
let wholesaleDecimal = ''
let lowDecimal = ''
for (let j = 0; j < this.meOldDataSource.length; j++) {
if(barCodeSku[i] === this.meOldDataSource[j].sku) {
currentBarCode = this.meOldDataSource[j].barCode
currentId = this.meOldDataSource[j].id
purchaseDecimal = this.meOldDataSource[j].purchaseDecimal
commodityDecimal = this.meOldDataSource[j].commodityDecimal
wholesaleDecimal = this.meOldDataSource[j].wholesaleDecimal
lowDecimal = this.meOldDataSource[j].lowDecimal
}
}
if(currentBarCode) {
//此时说明该sku之前就存在
meTableData.push({id: currentId, barCode: currentBarCode, commodityUnit: unit, sku: barCodeSku[i],
purchaseDecimal: purchaseDecimal, commodityDecimal: commodityDecimal,
wholesaleDecimal: wholesaleDecimal, lowDecimal: lowDecimal})
} else {
k = k+1
currentBarCode = addBigNumbers(maxBarCode, k)
meTableData.push({barCode: currentBarCode, commodityUnit: unit, sku: barCodeSku[i]})
}
}
this.meTable.dataSource = meTableData
}
})
} else {
this.$message.warning('请填写单位(注意不要勾选多单位,因为多属性商品不支持多单位)');
this.barCodeSwitch = false;
} }
if(this.getNumByField('skuTwo')) {
skuArr.push(skuTwoData)
}
if(this.getNumByField('skuThree')) {
skuArr.push(skuThreeData)
}
let skuArrOne = skuArr[0]
let skuArrTwo = skuArr[1]
let skuArrThree = skuArr[2]
let count = this.getNumByField('skuOne') + this.getNumByField('skuTwo') + this.getNumByField('skuThree')
let barCodeSku = []
if(count === 1) {
let skuArrOnly = []
if(this.getNumByField('skuOne')) {
skuArrOnly = skuOneData
} else if(this.getNumByField('skuTwo')) {
skuArrOnly = skuTwoData
} else if(this.getNumByField('skuThree')) {
skuArrOnly = skuThreeData
}
for (let i = 0; i < skuArrOnly.length; i++) {
barCodeSku.push(skuArrOnly[i])
}
} else if(count === 2) {
for (let i = 0; i < skuArrOne.length; i++) {
for (let j = 0; j < skuArrTwo.length; j++) {
barCodeSku.push(skuArrOne[i] + '/' + skuArrTwo[j])
}
}
} else if(count === 3) {
for (let i = 0; i < skuArrOne.length; i++) {
for (let j = 0; j < skuArrTwo.length; j++) {
for (let k = 0; k < skuArrThree.length; k++) {
barCodeSku.push(skuArrOne[i] + '/' + skuArrTwo[j] + '/' + skuArrThree[k])
}
}
}
}
let meTableData = []
getMaxBarCode({}).then((res)=>{
if(res && res.code===200) {
let k = 0
let maxBarCode = res.data.barCode
for (let i = 0; i < barCodeSku.length; i++) {
let currentBarCode = ''
let currentId = ''
let purchaseDecimal = ''
let commodityDecimal = ''
let wholesaleDecimal = ''
let lowDecimal = ''
for (let j = 0; j < this.meOldDataSource.length; j++) {
if(barCodeSku[i] === this.meOldDataSource[j].sku) {
currentBarCode = this.meOldDataSource[j].barCode
currentId = this.meOldDataSource[j].id
purchaseDecimal = this.meOldDataSource[j].purchaseDecimal
commodityDecimal = this.meOldDataSource[j].commodityDecimal
wholesaleDecimal = this.meOldDataSource[j].wholesaleDecimal
lowDecimal = this.meOldDataSource[j].lowDecimal
}
}
if(currentBarCode) {
//此时说明该sku之前就存在
meTableData.push({id: currentId, barCode: currentBarCode, commodityUnit: unit, sku: barCodeSku[i],
purchaseDecimal: purchaseDecimal, commodityDecimal: commodityDecimal,
wholesaleDecimal: wholesaleDecimal, lowDecimal: lowDecimal})
} else {
k = k+1
currentBarCode = addBigNumbers(maxBarCode, k)
meTableData.push({barCode: currentBarCode, commodityUnit: unit, sku: barCodeSku[i]})
}
}
this.meTable.dataSource = meTableData
}
})
}, },
getNumByField(field) { getNumByField(field) {
let num = 0 let num = 0

View File

@@ -57,9 +57,7 @@
<a>删除</a> <a>删除</a>
</a-popconfirm> </a-popconfirm>
<a-divider type="vertical"/> <a-divider type="vertical"/>
<a-popconfirm title="确定重置密码为123456吗?" @confirm="() => handleReset(record.id)"> <a @click="handleResetModal(record)">重置密码</a>
<a>重置密码</a>
</a-popconfirm>
</span> </span>
<!-- 状态渲染模板 --> <!-- 状态渲染模板 -->
<template slot="customRenderFlag" slot-scope="status"> <template slot="customRenderFlag" slot-scope="status">
@@ -72,6 +70,7 @@
<user-modal ref="modalForm" @ok="modalFormOk"></user-modal> <user-modal ref="modalForm" @ok="modalFormOk"></user-modal>
<user-depot-modal ref="userDepotModal" @ok="modalFormOk"></user-depot-modal> <user-depot-modal ref="userDepotModal" @ok="modalFormOk"></user-depot-modal>
<user-customer-modal ref="userCustomerModal" @ok="modalFormOk"></user-customer-modal> <user-customer-modal ref="userCustomerModal" @ok="modalFormOk"></user-customer-modal>
<user-reset-modal ref="userResetModal" @ok="modalFormOk"></user-reset-modal>
</a-card> </a-card>
</a-col> </a-col>
</a-row> </a-row>
@@ -81,6 +80,7 @@
import UserModal from './modules/UserModal' import UserModal from './modules/UserModal'
import UserDepotModal from './modules/UserDepotModal' import UserDepotModal from './modules/UserDepotModal'
import UserCustomerModal from './modules/UserCustomerModal' import UserCustomerModal from './modules/UserCustomerModal'
import UserResetModal from './modules/UserResetModal'
import {postAction} from '@/api/manage'; import {postAction} from '@/api/manage';
import {getCurrentSystemConfig} from '@/api/api' import {getCurrentSystemConfig} from '@/api/api'
import {JeecgListMixin} from '@/mixins/JeecgListMixin' import {JeecgListMixin} from '@/mixins/JeecgListMixin'
@@ -92,6 +92,7 @@
UserModal, UserModal,
UserDepotModal, UserDepotModal,
UserCustomerModal, UserCustomerModal,
UserResetModal,
JInput JInput
}, },
data() { data() {
@@ -175,6 +176,10 @@
this.$refs.modalForm.isReadOnly = true this.$refs.modalForm.isReadOnly = true
} }
}, },
handleResetModal(record) {
this.$refs.userResetModal.edit(record);
this.$refs.userResetModal.title = "请输入" + record.loginName + "的新密码";
},
handleReset(id) { handleReset(id) {
let that = this; let that = this;
postAction(that.url.resetPwd, {id: id}).then((res) => { postAction(that.url.resetPwd, {id: id}).then((res) => {

View File

@@ -14,7 +14,7 @@
@cancel="handleCancel" @cancel="handleCancel"
cancelText="取消" cancelText="取消"
okText="保存" okText="保存"
style="top:5%;height: 85%;"> style="top:2%;height:95%;">
<template slot="footer"> <template slot="footer">
<a-button key="back" v-if="isReadOnly" @click="handleCancel"> <a-button key="back" v-if="isReadOnly" @click="handleCancel">
取消 取消
@@ -23,8 +23,10 @@
<a-spin :spinning="confirmLoading"> <a-spin :spinning="confirmLoading">
<a-form :form="form" id="userModal"> <a-form :form="form" id="userModal">
<a-form-item label="登录名称" :labelCol="labelCol" :wrapperCol="wrapperCol"> <a-form-item label="登录名称" :labelCol="labelCol" :wrapperCol="wrapperCol">
<a-input placeholder="请输入登录名称" v-decorator.trim="[ 'loginName', validatorRules.loginName]" :readOnly="!!model.id" <a-input placeholder="请输入登录名称" v-decorator.trim="[ 'loginName', validatorRules.loginName]" :readOnly="!!model.id" />
suffix="初始密码123456" /> </a-form-item>
<a-form-item label="用户密码" :labelCol="labelCol" :wrapperCol="wrapperCol" v-if="!model.id">
<a-input-password placeholder="请输入用户密码" v-decorator.trim="[ 'password', validatorRules.password]" />
</a-form-item> </a-form-item>
<a-form-item label="用户姓名" :labelCol="labelCol" :wrapperCol="wrapperCol" > <a-form-item label="用户姓名" :labelCol="labelCol" :wrapperCol="wrapperCol" >
<a-input placeholder="请输入用户姓名" v-decorator.trim="[ 'username', validatorRules.username]" /> <a-input placeholder="请输入用户姓名" v-decorator.trim="[ 'username', validatorRules.username]" />
@@ -71,11 +73,10 @@
<script> <script>
import pick from 'lodash.pick' import pick from 'lodash.pick'
import Vue from 'vue' import Vue from 'vue'
import md5 from 'md5'
import JSelectPosition from '@/components/jeecgbiz/JSelectPosition' import JSelectPosition from '@/components/jeecgbiz/JSelectPosition'
import { ACCESS_TOKEN } from "@/store/mutation-types" import { ACCESS_TOKEN } from "@/store/mutation-types"
import { getAction } from '@/api/manage'
import {addUser,editUser,queryOrganizationTreeList,roleAllList} from '@/api/api' import {addUser,editUser,queryOrganizationTreeList,roleAllList} from '@/api/api'
import { disabledAuthFilter } from "@/utils/authFilter"
import {autoJumpNextInput} from "@/utils/util" import {autoJumpNextInput} from "@/utils/util"
import {mixinDevice} from '@/utils/mixin' import {mixinDevice} from '@/utils/mixin'
import JImageUpload from '../../../components/jeecg/JImageUpload' import JImageUpload from '../../../components/jeecg/JImageUpload'
@@ -105,6 +106,12 @@
required: true, message: '请输入登录名称!' required: true, message: '请输入登录名称!'
}] }]
}, },
password: {
rules: [
{ required: true, message: '请输入用户密码!' },
{ pattern: /^(?=.*[a-z])(?=.*\d).{6,}$/, message: '用户密码至少要有数字和小写字母并且长度至少6位!' }
]
},
username:{ username:{
rules: [{ rules: [{
required: true, message: '请输入用户姓名!' required: true, message: '请输入用户姓名!'
@@ -168,6 +175,7 @@
let obj; let obj;
if(!this.model.id){ if(!this.model.id){
formData.id = this.userId; formData.id = this.userId;
formData.password = md5(values.password);
obj=addUser(formData); obj=addUser(formData);
}else{ }else{
obj=editUser(formData); obj=editUser(formData);

View File

@@ -0,0 +1,109 @@
<template>
<div ref="container">
<a-modal
:title="title"
:width="600"
:visible="visible"
:confirmLoading="confirmLoading"
:getContainer="() => $refs.container"
:maskStyle="{'top':'93px','left':'154px'}"
:wrapClassName="wrapClassNameInfo()"
:mask="isDesktop()"
:maskClosable="false"
@ok="handleOk"
@cancel="handleCancel"
cancelText="取消"
okText="保存"
style="top:25%;height:35%;">
<a-spin :spinning="confirmLoading">
<a-form :form="form">
<a-form-item :labelCol="labelCol" :wrapperCol="wrapperCol" label="新密码">
<a-input-password placeholder="请输入新密码" v-decorator.trim="[ 'password', validatorRules.password]" />
</a-form-item>
</a-form>
</a-spin>
</a-modal>
</div>
</template>
<script>
import md5 from 'md5'
import pick from 'lodash.pick'
import { resetPwd } from '@/api/api'
import {mixinDevice} from '@/utils/mixin'
export default {
name: "UserResetModal",
mixins: [mixinDevice],
data () {
return {
title:"操作",
visible: false,
model: {},
maskStyle: '',
labelCol: {
xs: { span: 24 },
sm: { span: 5 },
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 16 },
},
confirmLoading: false,
form: this.$form.createForm(this),
validatorRules:{
password:{
rules: [
{ required: true, message: '请输入新密码!' },
{ pattern: /^(?=.*[a-z])(?=.*\d).{6,}$/, message: '用户密码至少要有数字和小写字母并且长度至少6位!' }
]
}
},
}
},
created () {
},
methods: {
add () {
this.edit({});
},
edit (record) {
this.form.resetFields();
this.model = Object.assign({}, record);
this.visible = true;
this.$nextTick(() => {
this.form.setFieldsValue(pick(this.model, 'password'))
});
},
close () {
this.$emit('close');
this.visible = false;
},
handleOk () {
const that = this;
// 触发表单验证
this.form.validateFields((err, values) => {
if (!err) {
that.confirmLoading = true;
let formData = Object.assign(this.model, values);
let bodyParam = {
id: formData.id,
password: md5(formData.password)
}
resetPwd(bodyParam).then((res)=>{
if(res.code === 200){
that.$emit('ok');
}else{
that.$message.warning(res.data.message);
}
}).finally(() => {
that.confirmLoading = false;
that.close();
})
}
})
},
handleCancel () {
this.close()
}
}
}
</script>