浏览代码

门店管理

fanzherong_v 3 月之前
父节点
当前提交
6fe91a2b59

+ 2 - 1
snowy-admin-web/package.json

@@ -38,12 +38,13 @@
 		"fuse.js": "7.0.0",
 		"fuse.js": "7.0.0",
 		"highlight.js": "11.10.0",
 		"highlight.js": "11.10.0",
 		"hotkeys-js": "3.13.7",
 		"hotkeys-js": "3.13.7",
+		"html2canvas": "^1.4.1",
 		"js-pinyin": "0.2.7",
 		"js-pinyin": "0.2.7",
 		"lodash-es": "4.17.21",
 		"lodash-es": "4.17.21",
 		"nprogress": "0.2.0",
 		"nprogress": "0.2.0",
 		"pinia": "2.2.2",
 		"pinia": "2.2.2",
-		"screenfull": "6.0.2",
 		"qs": "6.13.0",
 		"qs": "6.13.0",
+		"screenfull": "6.0.2",
 		"sm-crypto": "0.3.13",
 		"sm-crypto": "0.3.13",
 		"snowflake-id": "1.1.0",
 		"snowflake-id": "1.1.0",
 		"sortablejs": "1.15.3",
 		"sortablejs": "1.15.3",

+ 6 - 6
snowy-admin-web/src/views/biz/org/form.vue

@@ -7,12 +7,12 @@
 		@close="onClose"
 		@close="onClose"
 	>
 	>
 		<a-form ref="formRef" :model="formData" :rules="formRules" layout="vertical">
 		<a-form ref="formRef" :model="formData" :rules="formRules" layout="vertical">
-			<a-form-item label="上级机构:" name="parentId">
+			<a-form-item label="上级组织:" name="parentId">
 				<a-tree-select
 				<a-tree-select
 					v-model:value="formData.parentId"
 					v-model:value="formData.parentId"
 					class="xn-wd"
 					class="xn-wd"
 					:dropdown-style="{ maxHeight: '400px', overflow: 'auto' }"
 					:dropdown-style="{ maxHeight: '400px', overflow: 'auto' }"
-					placeholder="请选择上级机构"
+					placeholder="请选择上级组织"
 					allow-clear
 					allow-clear
 					tree-default-expand-all
 					tree-default-expand-all
 					:tree-data="treeData"
 					:tree-data="treeData"
@@ -25,18 +25,18 @@
 					tree-line
 					tree-line
 				/>
 				/>
 			</a-form-item>
 			</a-form-item>
-			<a-form-item label="机构名称:" name="name">
+			<a-form-item label="门店名称:" name="name">
 				<a-input v-model:value="formData.name" placeholder="请输入机构名称" allow-clear />
 				<a-input v-model:value="formData.name" placeholder="请输入机构名称" allow-clear />
 			</a-form-item>
 			</a-form-item>
-			<a-form-item label="机构地址:" name="name">
+			<a-form-item label="门店地址:" name="address">
 				<a-input v-model:value="formData.address" placeholder="请输入门店地址" allow-clear />
 				<a-input v-model:value="formData.address" placeholder="请输入门店地址" allow-clear />
 			</a-form-item>
 			</a-form-item>
-			<a-form-item label="机构分类:" name="category">
+			<a-form-item label="组织分类:" name="category">
 				<a-select
 				<a-select
 					v-model:value="formData.category"
 					v-model:value="formData.category"
 					:options="orgCategoryOptions"
 					:options="orgCategoryOptions"
 					class="xn-wd"
 					class="xn-wd"
-					placeholder="请选择机构分类"
+					placeholder="请选择组织分类"
 				/>
 				/>
 			</a-form-item>
 			</a-form-item>
 			<a-form-item label="排序:" name="sortCode">
 			<a-form-item label="排序:" name="sortCode">

+ 115 - 6
snowy-admin-web/src/views/biz/org/index.vue

@@ -18,7 +18,7 @@
 					<a-row :gutter="24">
 					<a-row :gutter="24">
 						<a-col :span="8">
 						<a-col :span="8">
 							<a-form-item name="searchKey" label="名称关键词">
 							<a-form-item name="searchKey" label="名称关键词">
-								<a-input v-model:value="searchFormState.searchKey" placeholder="请输入机构名称关键词" />
+								<a-input v-model:value="searchFormState.searchKey" placeholder="请输入门店名称关键词" />
 							</a-form-item>
 							</a-form-item>
 						</a-col>
 						</a-col>
 						<a-col :span="8">
 						<a-col :span="8">
@@ -71,6 +71,8 @@
 							{{ $TOOL.dictTypeData('ORG_CATEGORY', record.category) }}
 							{{ $TOOL.dictTypeData('ORG_CATEGORY', record.category) }}
 						</template>
 						</template>
 						<template v-if="column.dataIndex === 'action'">
 						<template v-if="column.dataIndex === 'action'">
+							<a @click="showModal(record)" >二维码</a>
+							<a-divider type="vertical" />
 							<a @click="formRef.onOpen(record)" v-if="hasPerm('bizOrgEdit')">编辑</a>
 							<a @click="formRef.onOpen(record)" v-if="hasPerm('bizOrgEdit')">编辑</a>
 							<a-divider type="vertical" v-if="hasPerm(['bizOrgEdit', 'bizOrgDelete'], 'and')" />
 							<a-divider type="vertical" v-if="hasPerm(['bizOrgEdit', 'bizOrgDelete'], 'and')" />
 							<a-popconfirm title="删除此机构与下级机构吗?" @confirm="removeOrg(record)">
 							<a-popconfirm title="删除此机构与下级机构吗?" @confirm="removeOrg(record)">
@@ -83,6 +85,30 @@
 		</a-col>
 		</a-col>
 	</a-row>
 	</a-row>
 	<Form ref="formRef" @successful="tableRef.refresh()" />
 	<Form ref="formRef" @successful="tableRef.refresh()" />
+
+	<a-modal v-model:visible="open" title="二维码">
+		<div id="qrcode" style="text-align: center; margin: 15px;">
+			<a-row>
+				<a-col :span="14">
+					<br><br>
+					<p><span>门店名称:</span>{{nowRecord.name}}</p>
+					<p><span>门店编码:</span>{{ nowRecord.code }}</p>
+				</a-col>
+				<a-col :span="8">
+					<a-image width="206" :src="qrCodeUrl.codeUrl">
+						<template #default>
+							<img src="https://www.antdv.com/assets/logo.1ef800a8.svg" class="icon" alt="Icon" />
+						</template>
+					</a-image>
+				</a-col>
+			</a-row>
+
+		</div>
+		<template #footer>
+			<a-button @click="closeQrCode">关闭</a-button>
+			<a-button type="primary" @click="downloadFile">下载</a-button>
+		</template>
+	</a-modal>
 </template>
 </template>
 
 
 <script setup name="bizOrg">
 <script setup name="bizOrg">
@@ -90,20 +116,34 @@
 	import { isEmpty } from 'lodash-es'
 	import { isEmpty } from 'lodash-es'
 	import bizOrgApi from '@/api/biz/bizOrgApi'
 	import bizOrgApi from '@/api/biz/bizOrgApi'
 	import Form from './form.vue'
 	import Form from './form.vue'
+	import QRCode from 'qrcode'
+	import html2canvas from 'html2canvas'
 
 
 	const columns = [
 	const columns = [
 		{
 		{
-			title: '机构名称',
-			dataIndex: 'name'
+			title: '门店名称',
+			dataIndex: 'name',
+			width:150
+		},
+		{
+			title: '门店编码',
+			dataIndex: 'code',
+			width:150
+		},
+		{
+			title: '门店地址',
+			dataIndex: 'address',
+			width:200
 		},
 		},
 		{
 		{
 			title: '分类',
 			title: '分类',
-			dataIndex: 'category'
+			dataIndex: 'category',
+			width: 100
 		},
 		},
 		{
 		{
 			title: '排序',
 			title: '排序',
 			dataIndex: 'sortCode',
 			dataIndex: 'sortCode',
-			width: 100
+			width: 80
 		}
 		}
 	]
 	]
 	if (hasPerm(['bizOrgEdit', 'bizOrgDelete'])) {
 	if (hasPerm(['bizOrgEdit', 'bizOrgDelete'])) {
@@ -111,7 +151,7 @@
 			title: '操作',
 			title: '操作',
 			dataIndex: 'action',
 			dataIndex: 'action',
 			align: 'center',
 			align: 'center',
-			width: '150px'
+			width: 150
 		})
 		})
 	}
 	}
 	const selectedRowKeys = ref([])
 	const selectedRowKeys = ref([])
@@ -209,6 +249,75 @@
 			tableRef.value.clearRefreshSelected()
 			tableRef.value.clearRefreshSelected()
 		})
 		})
 	}
 	}
+
+	//二维码
+	const open = ref(false);
+	const qrCodeUrl = ref({})
+	const qrcodeCanvasRef = ref();
+	const nowRecord = ref({})
+
+	const showModal = (record) => {
+		nowRecord.value = record
+		open.value = true;
+		getQrCode(record)
+
+	};
+
+	const getQrCode = (record) => {
+		//QRCode.toDataURL("id:"+record.id+"saleCode:"+record.saleCode, {
+		let param = {
+			id:record.id,
+			code:record.code
+		}
+		QRCode.toDataURL(JSON.stringify(param), {
+			errorCorrectionLevel: 'H',
+			margin: 1,
+			height: 206,
+			width: 206,
+			type: '10',
+			scal: 177,
+			color: {
+				dark: '#000' // 二维码背景颜色
+			},
+			rendererOpts: {
+				quality: 0.9
+			},
+			icon:'/public/img/tanglogo.png'
+		})
+			.then((url) => {
+				qrCodeUrl.value.codeUrl = url
+			})
+			.catch((err) => {
+				console.error(err)
+			})
+	}
+
+	const closeQrCode = () => {
+		open.value = false;
+	}
+
+	// 下载二维码
+	const downloadFile = () => {
+		html2canvas(qrcode, {
+			logging: false,
+			allowTaint: true,
+			scale: window.devicePixelRatio,
+			scrollY: 0,
+			scrollX: 0,
+			useCORS: true,
+			backgroundColor: '#ffffff'
+		})
+			.then(function (canvas) {
+				const a = window.document.createElement('a')
+				a.href = canvas.toDataURL('image/png')
+				a.download = '二维码'
+				a.click()
+				this.$message.success('正在进行下载保存')
+			})
+			.catch((err) => {
+				console.log(err)
+			})
+	}
 </script>
 </script>
 
 
 <style scoped>
 <style scoped>

+ 5 - 5
snowy-admin-web/src/views/sys/org/form.vue

@@ -1,6 +1,6 @@
 <template>
 <template>
 	<xn-form-container
 	<xn-form-container
-		:title="formData.id ? '编辑组织' : '增加组织'"
+		:title="formData.id ? '编辑门店' : '增加门店'"
 		:width="550"
 		:width="550"
 		:visible="visible"
 		:visible="visible"
 		:destroy-on-close="true"
 		:destroy-on-close="true"
@@ -25,11 +25,11 @@
 					tree-line
 					tree-line
 				/>
 				/>
 			</a-form-item>
 			</a-form-item>
-			<a-form-item label="组织名称:" name="name">
-				<a-input v-model:value="formData.name" placeholder="请输入组织名称" allow-clear />
+			<a-form-item label="门店名称:" name="name">
+				<a-input v-model:value="formData.name" placeholder="请输入门店名称" allow-clear />
 			</a-form-item>
 			</a-form-item>
-			<a-form-item label="组织地址:" name="address">
-				<a-input v-model:value="formData.address" placeholder="请输入组织地址" allow-clear />
+			<a-form-item label="门店地址:" name="address">
+				<a-input v-model:value="formData.address" placeholder="请输入门店地址" allow-clear />
 			</a-form-item>
 			</a-form-item>
 			<a-form-item label="组织分类:" name="category">
 			<a-form-item label="组织分类:" name="category">
 				<a-select
 				<a-select

+ 119 - 6
snowy-admin-web/src/views/sys/org/index.vue

@@ -18,7 +18,7 @@
 					<a-row :gutter="24">
 					<a-row :gutter="24">
 						<a-col :span="8">
 						<a-col :span="8">
 							<a-form-item name="searchKey" label="名称关键词">
 							<a-form-item name="searchKey" label="名称关键词">
-								<a-input v-model:value="searchFormState.searchKey" placeholder="请输入组织名称关键词" />
+								<a-input v-model:value="searchFormState.searchKey" placeholder="请输入门店名称关键词" />
 							</a-form-item>
 							</a-form-item>
 						</a-col>
 						</a-col>
 						<a-col :span="8">
 						<a-col :span="8">
@@ -65,6 +65,8 @@
 							{{ $TOOL.dictTypeData('ORG_CATEGORY', record.category) }}
 							{{ $TOOL.dictTypeData('ORG_CATEGORY', record.category) }}
 						</template>
 						</template>
 						<template v-if="column.dataIndex === 'action'">
 						<template v-if="column.dataIndex === 'action'">
+							<a @click="showModal(record)" >二维码</a>
+							<a-divider type="vertical" />
 							<a @click="formRef.onOpen(record)">编辑</a>
 							<a @click="formRef.onOpen(record)">编辑</a>
 							<a-divider type="vertical" />
 							<a-divider type="vertical" />
 							<a-popconfirm title="删除此组织与下级组织吗?" @confirm="removeOrg(record)">
 							<a-popconfirm title="删除此组织与下级组织吗?" @confirm="removeOrg(record)">
@@ -77,6 +79,31 @@
 		</a-col>
 		</a-col>
 	</a-row>
 	</a-row>
 	<Form ref="formRef" @successful="tableRef.refresh()" />
 	<Form ref="formRef" @successful="tableRef.refresh()" />
+
+
+	<a-modal v-model:visible="open" title="二维码">
+		<div id="qrcode" style="text-align: center; margin: 15px;">
+			<a-row>
+				<a-col :span="14">
+					<br><br>
+					<p><span>门店名称:</span>{{nowRecord.name}}</p>
+					<p><span>门店编码:</span>{{ nowRecord.code }}</p>
+				</a-col>
+				<a-col :span="8">
+					<a-image width="206" :src="qrCodeUrl.codeUrl">
+						<template #default>
+							<img src="https://www.antdv.com/assets/logo.1ef800a8.svg" class="icon" alt="Icon" />
+						</template>
+					</a-image>
+				</a-col>
+			</a-row>
+
+		</div>
+		<template #footer>
+			<a-button @click="closeQrCode">关闭</a-button>
+			<a-button type="primary" @click="downloadFile">下载</a-button>
+		</template>
+	</a-modal>
 </template>
 </template>
 
 
 <script setup name="sysOrg">
 <script setup name="sysOrg">
@@ -84,15 +111,24 @@
 	import { isEmpty } from 'lodash-es'
 	import { isEmpty } from 'lodash-es'
 	import orgApi from '@/api/sys/orgApi'
 	import orgApi from '@/api/sys/orgApi'
 	import Form from './form.vue'
 	import Form from './form.vue'
+	import QRCode from 'qrcode'
+	import html2canvas from 'html2canvas'
 
 
 	const columns = [
 	const columns = [
 		{
 		{
-			title: '组织名称',
-			dataIndex: 'name'
+			title: '门店名称',
+			dataIndex: 'name',
+			width:150
 		},
 		},
 		{
 		{
-			title: '组织地址',
-			dataIndex: 'address'
+			title: '门店编码',
+			dataIndex: 'code',
+			width:150
+		},
+		{
+			title: '门店地址',
+			dataIndex: 'address',
+			width:200
 		},
 		},
 		{
 		{
 			title: '分类',
 			title: '分类',
@@ -108,7 +144,7 @@
 			title: '操作',
 			title: '操作',
 			dataIndex: 'action',
 			dataIndex: 'action',
 			align: 'center',
 			align: 'center',
-			width: '150px'
+			width: 150
 		}
 		}
 	]
 	]
 	const selectedRowKeys = ref([])
 	const selectedRowKeys = ref([])
@@ -200,6 +236,76 @@
 			tableRef.value.clearRefreshSelected()
 			tableRef.value.clearRefreshSelected()
 		})
 		})
 	}
 	}
+
+
+	//二维码
+	const open = ref(false);
+	const qrCodeUrl = ref({})
+	const qrcodeCanvasRef = ref();
+	const nowRecord = ref({})
+
+	const showModal = (record) => {
+		nowRecord.value = record
+		open.value = true;
+		getQrCode(record)
+
+	};
+
+	const getQrCode = (record) => {
+		//QRCode.toDataURL("id:"+record.id+"saleCode:"+record.saleCode, {
+		let param = {
+			id:record.id,
+			code:record.code
+		}
+		QRCode.toDataURL(JSON.stringify(param), {
+			errorCorrectionLevel: 'H',
+			margin: 1,
+			height: 206,
+			width: 206,
+			type: '10',
+			scal: 177,
+			color: {
+				dark: '#000' // 二维码背景颜色
+			},
+			rendererOpts: {
+				quality: 0.9
+			},
+			icon:'/public/img/tanglogo.png'
+		})
+			.then((url) => {
+				qrCodeUrl.value.codeUrl = url
+			})
+			.catch((err) => {
+				console.error(err)
+			})
+	}
+
+	const closeQrCode = () => {
+		open.value = false;
+	}
+
+	// 下载二维码
+	const downloadFile = () => {
+		html2canvas(qrcode, {
+			logging: false,
+			allowTaint: true,
+			scale: window.devicePixelRatio,
+			scrollY: 0,
+			scrollX: 0,
+			useCORS: true,
+			backgroundColor: '#ffffff'
+		})
+			.then(function (canvas) {
+				const a = window.document.createElement('a')
+				a.href = canvas.toDataURL('image/png')
+				a.download = '二维码'
+				a.click()
+				this.$message.success('正在进行下载保存')
+			})
+			.catch((err) => {
+				console.log(err)
+			})
+	}
 </script>
 </script>
 
 
 <style scoped>
 <style scoped>
@@ -209,4 +315,11 @@
 	.snowy-button-left {
 	.snowy-button-left {
 		margin-left: 8px;
 		margin-left: 8px;
 	}
 	}
+	.icon {
+		position: absolute;
+		top: 10px;
+		right: 10px;
+		width: 40px;
+		height: 40px;
+	}
 </style>
 </style>

+ 4 - 0
snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/param/BizOrgAddParam.java

@@ -55,4 +55,8 @@ public class BizOrgAddParam {
     /** 扩展JSON */
     /** 扩展JSON */
     @Schema(description = "扩展JSON")
     @Schema(description = "扩展JSON")
     private String extJson;
     private String extJson;
+
+    /** 门店地址 */
+    @Schema(description = "门店地址")
+    private String address;
 }
 }

+ 4 - 0
snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/param/BizOrgEditParam.java

@@ -60,4 +60,8 @@ public class BizOrgEditParam {
     /** 扩展JSON */
     /** 扩展JSON */
     @Schema(description = "扩展JSON")
     @Schema(description = "扩展JSON")
     private String extJson;
     private String extJson;
+
+    /** 门店地址 */
+    @Schema(description = "门店地址")
+    private String address;
 }
 }

+ 3 - 3
snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/org/service/impl/BizOrgServiceImpl.java

@@ -63,10 +63,10 @@ import java.util.stream.Collectors;
 public class BizOrgServiceImpl extends ServiceImpl<BizOrgMapper, BizOrg> implements BizOrgService {
 public class BizOrgServiceImpl extends ServiceImpl<BizOrgMapper, BizOrg> implements BizOrgService {
 
 
     public static final String ORG_CACHE_ALL_KEY = "sys-org:all";
     public static final String ORG_CACHE_ALL_KEY = "sys-org:all";
-    
+
     @Resource
     @Resource
     private CommonCacheOperator commonCacheOperator;
     private CommonCacheOperator commonCacheOperator;
-    
+
     @Resource
     @Resource
     private SysRoleApi sysRoleApi;
     private SysRoleApi sysRoleApi;
 
 
@@ -80,7 +80,7 @@ public class BizOrgServiceImpl extends ServiceImpl<BizOrgMapper, BizOrg> impleme
     public Page<BizOrg> page(BizOrgPageParam bizOrgPageParam) {
     public Page<BizOrg> page(BizOrgPageParam bizOrgPageParam) {
         QueryWrapper<BizOrg> queryWrapper = new QueryWrapper<BizOrg>().checkSqlInjection();
         QueryWrapper<BizOrg> queryWrapper = new QueryWrapper<BizOrg>().checkSqlInjection();
         // 查询部分字段
         // 查询部分字段
-        queryWrapper.lambda().select(BizOrg::getId, BizOrg::getParentId, BizOrg::getName,
+        queryWrapper.lambda().select(BizOrg::getId, BizOrg::getParentId, BizOrg::getName, BizOrg::getCode, BizOrg::getAddress,
                 BizOrg::getCategory, BizOrg::getSortCode);
                 BizOrg::getCategory, BizOrg::getSortCode);
         if(ObjectUtil.isNotEmpty(bizOrgPageParam.getParentId())) {
         if(ObjectUtil.isNotEmpty(bizOrgPageParam.getParentId())) {
             queryWrapper.lambda().eq(BizOrg::getParentId, bizOrgPageParam.getParentId());
             queryWrapper.lambda().eq(BizOrg::getParentId, bizOrgPageParam.getParentId());

+ 4 - 0
snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/param/SysOrgAddParam.java

@@ -55,4 +55,8 @@ public class SysOrgAddParam {
     /** 扩展JSON */
     /** 扩展JSON */
     @Schema(description = "扩展JSON")
     @Schema(description = "扩展JSON")
     private String extJson;
     private String extJson;
+
+    /** 门店地址*/
+    @Schema(description = "门店地址")
+    private String address;
 }
 }

+ 4 - 0
snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/param/SysOrgEditParam.java

@@ -60,4 +60,8 @@ public class SysOrgEditParam {
     /** 扩展JSON */
     /** 扩展JSON */
     @Schema(description = "扩展JSON")
     @Schema(description = "扩展JSON")
     private String extJson;
     private String extJson;
+
+    /** 门店地址*/
+    @Schema(description = "门店地址")
+    private String address;
 }
 }

+ 1 - 1
snowy-plugin/snowy-plugin-sys/src/main/java/vip/xiaonuo/sys/modular/org/service/impl/SysOrgServiceImpl.java

@@ -79,7 +79,7 @@ public class SysOrgServiceImpl extends ServiceImpl<SysOrgMapper, SysOrg> impleme
     public Page<SysOrg> page(SysOrgPageParam sysOrgPageParam) {
     public Page<SysOrg> page(SysOrgPageParam sysOrgPageParam) {
         QueryWrapper<SysOrg> queryWrapper = new QueryWrapper<SysOrg>().checkSqlInjection();
         QueryWrapper<SysOrg> queryWrapper = new QueryWrapper<SysOrg>().checkSqlInjection();
         // 查询部分字段
         // 查询部分字段
-        queryWrapper.lambda().select(SysOrg::getId, SysOrg::getParentId, SysOrg::getName,
+        queryWrapper.lambda().select(SysOrg::getId, SysOrg::getParentId, SysOrg::getName, SysOrg::getCode, SysOrg::getAddress,
                 SysOrg::getCategory, SysOrg::getSortCode);
                 SysOrg::getCategory, SysOrg::getSortCode);
         if(ObjectUtil.isNotEmpty(sysOrgPageParam.getParentId())) {
         if(ObjectUtil.isNotEmpty(sysOrgPageParam.getParentId())) {
             queryWrapper.lambda().eq(SysOrg::getParentId, sysOrgPageParam.getParentId());
             queryWrapper.lambda().eq(SysOrg::getParentId, sysOrgPageParam.getParentId());