asd26269546 il y a 1 an
Parent
commit
15801aee25

+ 6 - 1
src/assets/css/index.scss

@@ -30,6 +30,10 @@ li {
     color: #FF655B;
 }
 
+.cl-yl{
+    color: #FFB800;
+}
+
 #app {}
 
 .commons-title {
@@ -111,7 +115,7 @@ li {
     width: 100%;
     border-collapse: collapse;
     border-spacing: 0;
-
+    overflow-x: auto;
     table {
         width: 100%;
         border-collapse: collapse;
@@ -122,6 +126,7 @@ li {
             background-color: #F1F1F1;
             color: #666666;
             padding: 15px 0;
+            min-width: 100px;
         }
 
         td {

+ 19 - 2
src/lang/cn.js

@@ -2,7 +2,7 @@
 export const lang = {
 	common:{
 		//消息,工作台,物联网,我的,请输入关键词,添加没有更多了,释放即可刷新,下拉即可刷新,加载中,加载失败,加载完成,没有更多了,返回,提交,修改成功,新增成功,删除成功,确定,取消,提示,自动,手动,正常,运行,离线,明细,请选择,删除,添加明细,标题,请添加明细
-		//操作成功,产品明细,设备状态,正常,工作模式,自动,设备参数,型号
+		//操作成功,产品明细,设备状态,正常,工作模式,自动,设备参数,型号,无匹配数据
 		message:'消息',
 		workbench:'工作台',
 		things:'物联网',
@@ -45,7 +45,16 @@ export const lang = {
 		upload:"上传",
 		daysAgo:'天之前',
 		hoursAgo:'小时之前',
-		minutesAgo:'分钟之前'
+		minutesAgo:'分钟之前',
+		searchResults:'搜索结果',
+		noMatchingData:'无匹配数据',
+	},
+	processApproval:{
+		//流程办理,流程类型,流程标题,发起人
+		name:'流程办理',
+		processType:'流程类型',
+		processTitle:'流程标题',
+		initiator:'发起人',
 	},
 	email:{
 		//收件箱,写邮件,搜索,邮箱,所有收件箱,账户,请选择邮箱,联系人,客户,收件箱,未读邮件,草稿箱,已发送,已删除,垃圾邮箱,发件人,收件人,时间,附件,下载,
@@ -812,6 +821,14 @@ export const lang = {
 		passwordCanNotBeEmpty:'密码不能为空',
 		roleCanNotBeEmpty:'角色不能为空',
 		phoneCanNotBeEmpty:'手机号不能为空',
+		//业务员管理,业务员新增,所属部门,员工姓名,业务代码,业务员代码
+		salesmanManagement:'业务员管理',
+		salesmanEdit:'业务员修改',
+		belongDept:'所属部门',
+		employeeName:'员工姓名',
+		businessCode:'业务代码',
+		salesmanCode:'业务员代码',
+
 	},
 	dict:{
 		//业务字典,键,值,排序,租户字典,键不能为空,值不能为空,排序不能为空,字典名称,字典编码,备注,启用状态,启用,禁用,状态不能为空,字典名称不能为空,字典编码不能为空

Fichier diff supprimé car celui-ci est trop grand
+ 0 - 21
src/lang/en.js


+ 20 - 4
src/router/index.js

@@ -72,12 +72,23 @@ const routes = [{
 				name: '消息列表',
 				component: () => import('../views/message/messageList.vue')
 			},
-
 			{
 				path: 'iframWinfaster',
 				name: '官网',
 				component: () => import('../views/working/iframWinfaster.vue')
 			},
+			//流程模块
+			{
+				path: 'processApproval',
+				name: '流程办理',
+				component: () => import('../views/processApproval/index.vue')
+			},
+			{
+				path: 'processDtl',
+				name: '流程办理-详情',
+				component: () => import('../views/processApproval/processDtl.vue')
+			},
+			
 			//公共模块
 			{
 				path: 'contractTemplateAdd',
@@ -172,9 +183,14 @@ const routes = [{
 				component: () => import('../views/system/dict/businessAdd.vue')
 			},
 			{
-				path: 'user',
-				name: '用户管理',
-				component: () => import('../views/system/user/index.vue')
+				path: 'salesman',
+				name: '业务员管理',
+				component: () => import('../views/system/salesman/index.vue')
+			},
+			{
+				path: 'salesmanAdd',
+				name: '业务员修改',
+				component: () => import('../views/system/salesman/add.vue')
 			},
 			{
 				path: 'userAdd',

+ 5 - 0
src/views/processApproval/components/SendSubscribe copy.vue

@@ -0,0 +1,5 @@
+<template>
+    <div>
+        12312312
+    </div>
+</template>

+ 5 - 0
src/views/processApproval/components/SendSubscribe.vue

@@ -0,0 +1,5 @@
+<template>
+    <div>
+        12312312
+    </div>
+</template>

+ 155 - 0
src/views/processApproval/index.vue

@@ -0,0 +1,155 @@
+<template>
+	<van-nav-bar
+		:title="$t('processApproval.name')"
+		left-text=""
+		left-arrow
+		@click-left="onClickLeft"
+		@click-right="onClickRight"
+	>
+	</van-nav-bar>
+	<van-search
+		v-model="req.keyword"
+		:placeholder="$t('common.pleaseEnterKeywords')"
+		@search="onRefresh"
+	/>
+	<van-pull-refresh v-model="loading" @refresh="onRefresh">
+		<div class="list">
+			<van-list
+				v-model:loading="loading"
+				:finished="finished"
+				:finished-text="$t('common.noMore')"
+				@load="onLoad"
+				style="margin-bottom: 60px"
+			>
+				<commonList
+					:data="listData"
+					@onClick="toDtl"
+					:config="listConfig"
+				></commonList>
+			</van-list>
+		</div>
+	</van-pull-refresh>
+</template>
+<script setup>
+import { ref, getCurrentInstance, onMounted } from 'vue'
+import commonList from '@/components/common-list.vue'
+import { useRoute } from 'vue-router'
+import { getUserInfo } from '@/utils/auth'
+
+const loading = ref(false)
+const route = useRoute()
+const req = ref({
+	pageNum: 1,
+	keyword: null,
+	definition: '1',
+	tenantId: getUserInfo().tenantId,
+})
+const finished = ref(false)
+const proxy = getCurrentInstance().proxy
+const listData = ref([])
+const listConfig = ref([
+	{
+		label: proxy.t('processApproval.processType'),
+		prop: 'flowName',
+	},
+	{
+		label: proxy.t('processApproval.initiator'),
+		prop: 'createUserName',
+	},
+	{
+		label: proxy.t('processApproval.processTitle'),
+		prop: 'title',
+	},
+])
+const onRefresh = () => {
+	req.value.pageNum = 1
+	finished.value = false
+	getList('refresh')
+}
+const onLoad = () => {
+	getList()
+}
+const onClickLeft = () => proxy.$router.push('/main/working')
+const onClickRight = () => {
+	proxy.$router.push({
+		path: 'userAdd',
+		query: {
+			type: 'add',
+		},
+	})
+}
+proxy.uploadDdRightBtn(onClickRight, proxy.t('common.add'))
+const toDtl = (row) => {
+	if (row.status != 1 && row.status != 0) {
+		proxy.$router.push({
+			path: '/main/processDtl',
+			query: {
+				flowKey: row.flowKey,
+				id: row.id,
+				processType: 20,
+				version: row.version,
+			},
+		})
+		return
+	}
+	proxy.post('flowExample/getApprovalRecord', { id: row.id }).then((res) => {
+		if (res.recordList.length > 0) {
+			let data = res.recordList.filter((item) => item.status === 2)
+			let nodeType = 0
+			if (data && data.length > 0) {
+				nodeType = data[0].nodeType
+			}
+			proxy.$router.push({
+				path: '/main/processDtl',
+				query: {
+					flowKey: row.flowKey,
+					id: row.id,
+					processType: nodeType == 1 ? 30 : 10,
+					version: row.version,
+				},
+			})
+		}
+	})
+	proxy.$router.push({
+		path: 'processDtl',
+		query: {
+			flowKey: row.flowKey,
+			id: row.id,
+			processType: 10,
+		},
+	})
+}
+onMounted(() => {
+	if (route.query) {
+		console.log(route.query)
+		req.value.status = route.query.status
+		getList()
+	}
+})
+
+const getList = (type) => {
+	loading.value = true
+	proxy
+		.post('/flowExample/getToBeProcessedPage', req.value)
+		.then((res) => {
+			listData.value =
+				type === 'refresh'
+					? res.data.rows
+					: listData.value.concat(res.data.rows)
+			if (req.value.pageNum * 10 >= res.data.total) {
+				finished.value = true
+			}
+			req.value.pageNum++
+			loading.value = false
+		})
+		.catch((err) => {
+			loading.value = false
+		})
+}
+</script>
+
+<style lang="scss" scoped>
+.list {
+	min-height: 70vh;
+}
+</style>

+ 328 - 0
src/views/processApproval/processDtl.vue

@@ -0,0 +1,328 @@
+<template>
+	<div class="process">
+		<van-nav-bar
+			title="流程审批"
+			left-text=""
+			left-arrow
+			@click-left="onClickLeft"
+		>
+		</van-nav-bar>
+        <component ref="makeDom" :is='componentObj[route.query.flowKey].component'></component>
+		<div class="card">
+			<div class="common-title border-btm">申购信息</div>
+			<div class="common-form-text">
+				<div class="common-form-text-item">
+					<div class="common-form-text-item-label">申购单号</div>
+					<div class="common-form-text-item-value">
+						PR-221101-170404-296
+					</div>
+				</div>
+				<div class="common-form-text-item">
+					<div class="common-form-text-item-label">申购时间</div>
+					<div class="common-form-text-item-value">
+						2022-11-01 17:04:04
+					</div>
+				</div>
+				<div class="common-form-text-item">
+					<div class="common-form-text-item-label">申购部门</div>
+					<div class="common-form-text-item-value">仓库</div>
+				</div>
+				<div class="common-form-text-item">
+					<div class="common-form-text-item-label">申购人</div>
+					<div class="common-form-text-item-value">阮平芳</div>
+				</div>
+				<div class="common-form-text-item">
+					<div class="common-form-text-item-label">申购类型</div>
+					<div class="common-form-text-item-value">物料</div>
+				</div>
+				<div class="common-form-text-item textarea">
+					<div class="common-form-text-item-label">申购说明</div>
+					<van-field
+						v-model="message"
+						rows="3"
+						autosize
+						type="textarea"
+						maxlength="400"
+						placeholder="请输入申购说明"
+						show-word-limit
+					/>
+				</div>
+			</div>
+		</div>
+		<div class="card">
+			<div class="common-title">申购明细</div>
+			<div class="common-mobile-table">
+				<table>
+					<thead>
+						<tr>
+							<th>物料编码</th>
+							<th>物料名称</th>
+							<th>规格型号</th>
+							<th>规格型号</th>
+							<th>规格型号</th>
+							<th>规格型号</th>
+							<th>规格型号</th>
+						</tr>
+					</thead>
+					<tbody>
+						<tr>
+							<td>1000000001</td>
+							<td>电脑</td>
+							<td>台</td>
+						</tr>
+						<tr>
+							<td>1000000002</td>
+							<td>显示器</td>
+							<td>台</td>
+						</tr>
+					</tbody>
+				</table>
+			</div>
+			<div class="more-btn">查看更多</div>
+		</div>
+		<div class="card">
+			<div class="common-title">审批流程</div>
+			<van-steps
+				direction="vertical"
+				:active="stepsNum"
+				class="common-steps"
+			>
+				<van-step v-for="(i, index) in recordList" :key="i.nodeId">
+					<div class="label">
+						<span class="name">{{ i.processedUser }}</span>
+						<span class="tip">{{ i.nodeName }}</span>
+						<span
+							class="state"
+							:class="
+								index == stepsNum
+									? 'cl-yl'
+									: index < stepsNum
+									? 'cl-blue'
+									: ''
+							"
+						>
+							{{ i.nodeName }}
+						</span>
+					</div>
+					<div class="content">审批意见:{{ i.remark }}</div>
+					<p>{{ i.processedDate }}</p>
+				</van-step>
+			</van-steps>
+			<div class="common-form-text">
+				<div class="common-form-text-item textarea">
+					<van-field
+						v-model="message"
+						rows="3"
+						autosize
+						type="textarea"
+						maxlength="400"
+						placeholder="请输入审批意见"
+						show-word-limit
+					/>
+				</div>
+				<div class="btn-warp">
+					<van-button
+						type="primary"
+						v-if="approvalRecordData.buttonInfoList.length == 0"
+						>同意</van-button
+					>
+					<van-button
+						type="primary"
+						v-else
+						v-for="i in approvalRecordData.buttonInfoList"
+						:key="i.type"
+						>{{ i.name }}</van-button
+					>
+				</div>
+			</div>
+		</div>
+	</div>
+</template>
+<script setup>
+import { ref, getCurrentInstance, onMounted, reactive } from 'vue'
+import { useRoute } from 'vue-router'
+import SendSubscribe from './components/SendSubscribe'
+const route = useRoute()
+const proxy = getCurrentInstance().proxy
+const onClickLeft = () => proxy.$router.push('/main/working')
+const message = ref('')
+const onClickRight = () => {
+	proxy.$router.push('/main/working')
+}
+let stepsNum = ref(0)
+let queryData = reactive({
+	data: {},
+})
+const flowForm = reactive({
+	flowKey: '',
+	tenantType: '',
+	handleUserId: '',
+	remark: '',
+	data: {},
+})
+let recordList = ref([])
+const approvalRecordData = ref({
+	buttonInfoList: [],
+})
+
+const getAuxiliaryData = (data)=>{
+  auxiliaryData.value=data
+}
+
+let componentObj = ref({
+	subscribe_flow: {
+		title: '申购',
+		component: SendSubscribe,
+		backUrl: '/main/subscribe',
+	},
+})
+
+let dialogVisible = ref(false);
+//判断是否有下一节点处理人
+const handleResult = (res) => {
+  if (res !== null && res.success) {
+    skipPage();
+  } else {
+    dialogVisible.value = true;
+    nextHandleUser.value = res.userList;
+  }
+};
+const skipPage = () => {
+    router.replace({
+      path: route.query.processType === 10 ?  "/main/processApproval" : componentObj[route.query.flowKey].backUrl,
+    });
+};
+
+const handleSelectUser = () => {
+	if (!flowForm.handleUserId) {
+		return ElMessage({
+			message: '请选择下一节点处理人!',
+			type: 'info',
+		})
+	}
+	handleSubmit()
+}
+const handleSubmit = async (_type) => {
+	const flag = await makeDom.value.handleSubmit()
+	if (flag) {
+		flowFormDom.value.validate((valid) => {
+			if (
+				route.query.processType == 10 ||
+				route.query.processType == 30
+			) {
+				proxy
+					.post('/flowProcess/jump', {
+						...flowForm,
+						data,
+						handleType: _type,
+						version: route.query.version,
+						flowId: route.query.id,
+					})
+					.then((res) => {
+						handleResult(res)
+					})
+				if (_type && _type == 1) {
+					proxy
+						.post('/flowExample/setStartData', {
+							exampleId: route.query.id,
+							startDate: data,
+						})
+						.then()
+				}
+				return
+			} else {
+				proxy
+					.post('/flowProcess/initiate', {
+						...flowForm,
+						data,
+					})
+					.then((res) => {
+						handleResult(res)
+					})
+			}
+		})
+	}
+}
+
+const getRecords = (_id) => {
+	if (_id) {
+		proxy
+			.post('/flowExample/getApprovalRecord', {
+				id: _id,
+			})
+			.then((res) => {
+				for (let i = 0; i < res.data.recordList.length; i++) {
+					const element = res.data.recordList[i]
+					if (element.status === 2) {
+						stepsNum.value = i
+						break
+					}
+				}
+				recordList.value = res.data.recordList
+				queryData.data.recordList = res.data.recordList
+				approvalRecordData.value = res.data
+			})
+	} else {
+		proxy
+			.post('/flowExample/getFlowNode', {
+				flowKey: flowForm.flowKey,
+			})
+			.then((res) => {
+				recordList.value = res.data
+				stepsNum.value = 0
+			})
+	}
+}
+onMounted(async () => {
+	//processType 10 为修改 20为查看 30回退发起 无为发起
+	if (
+		route.query.processType == 10 ||
+		route.query.processType == 20 ||
+		route.query.processType == 30
+	) {
+		await proxy
+			.post('/flowProcess/getStartData', { flowId: route.query.id })
+			.then((res) => {
+				queryData.data = { ...res }
+			})
+	} else {
+		queryData.data = { ...route.query }
+	}
+	flowForm.flowKey = route.query.flowKey
+	getRecords(route.query.id)
+})
+</script>
+<style lang="scss">
+.process {
+	padding-bottom: 60px;
+	.btn-warp {
+		display: flex;
+		justify-content: space-between;
+
+		margin: 20px 0 10px;
+		button {
+			width: 48%;
+		}
+	}
+	.card {
+		background: #fff;
+		padding: 0 12px;
+		margin-top: 10px;
+	}
+	.textarea {
+		.van-field {
+			border: none;
+			background: #f1f1f1;
+			border-radius: 5px;
+			padding: 5px 10px;
+		}
+	}
+	.more-btn {
+		height: 60px;
+		line-height: 60px;
+		font-size: 14px;
+		color: #0084ff;
+		text-align: center;
+	}
+}
+</style>

+ 6 - 6
src/views/procurementManagement/procureList/add.vue

@@ -14,7 +14,7 @@
 					is-link
 					readonly
 					:label="$t('procureList.procurementDepartment')"
-					placeholder="$t('procureList.selectProcurementDepartment')"
+					:placeholder="$t('procureList.selectProcurementDepartment')"
 					:rules="[{ required: true, message: $t('procureList.procurementDepartmentCanNotBeEmpty')}]"
 					:readonly="true"
 					required
@@ -24,7 +24,7 @@
 					type="text"
 					:name="$t('procureList.procurementPersonName')"
 					:label="$t('procureList.procurementPersonName')"
-					placeholder="$t('procureList.pleaseFillInTheProcurementPersonName')"
+					:placeholder="$t('procureList.pleaseFillInTheProcurementPersonName')"
 					:rules="[{ required: true, message: $t('procureList.procurementPersonNameCanNotBeEmpty') }]"
                     required
 					:readonly="true"
@@ -52,15 +52,15 @@
 					v-model="formData.supplyName"
 					is-link
 					readonly
-					label="$t('procureList.supplier')"
-					placeholder="$t('procureList.selectSupplier')"
+					:label="$t('procureList.supplier')"
+					:placeholder="$t('procureList.selectSupplier')"
 					@click=" typeModal = true"
 					:rules="[{ required: true, message: $t('procureList.supplierCanNotBeEmpty') }]"
 					required
 				/>
 				<van-popup v-model:show="typeModal" position="bottom">
 					<van-picker
-						title="$t('common.title')"
+						:title="$t('common.title')"
 						:columns="supplyList"
 						@confirm="onConfirm"
 						@cancel="typeModal = false"
@@ -153,7 +153,7 @@
 				v-model="formData.amount"
 				:name="$t('procureList.totalPrice')"
 				:label="$t('procureList.totalPrice')"
-				placeholder="$t('procureList.theTotalAmountOfAllDetails')"
+				:placeholder="$t('procureList.theTotalAmountOfAllDetails')"
 				:readonly="true"
 				type="number"
 			/>

+ 1 - 1
src/views/procurementManagement/procureList/index.vue

@@ -6,7 +6,7 @@
 		@click-left="onClickLeft"
 		@click-right="onClickRight"
 	>
-		<template #right> {{$t('manualInbound.purchase')}} </template>
+		<template #right> {{$t('procureList.purchase')}} </template>
 	</van-nav-bar>
 	<van-search
 		v-model="req.keyword"

+ 162 - 0
src/views/system/salesman/add.vue

@@ -0,0 +1,162 @@
+<template>
+  <div class="form">
+    <van-nav-bar
+      :title="$t('user.salesmanEdit')"
+      :left-text="$t('common.back')"
+      left-arrow
+      @click-left="onClickLeft"
+    >
+    </van-nav-bar>
+
+    <testForm
+      v-model="formData.data"
+      :formOption="formOption"
+      :formConfig="formConfig"
+      :rules="rules"
+      @onSubmit="onSubmit"
+      ref="formDom"
+    ></testForm>
+  </div>
+</template>
+
+<script setup>
+import { ref, getCurrentInstance, onMounted, reactive } from "vue";
+import { showSuccessToast, showToast } from "vant";
+import { useRoute } from "vue-router";
+import { getUserInfo } from "@/utils/auth";
+import testForm from "@/components/testForm/index.vue";
+import { handleTree } from "@/utils/ruoyi";
+const proxy = getCurrentInstance().proxy;
+const route = useRoute();
+const show = ref(false);
+const typeModal = ref(false);
+const unitModal = ref(false);
+const classification = ref([]);
+const formData = reactive({
+  data: {
+    tenantId: getUserInfo().tenantId
+  },
+});
+const formDom = ref(null);
+const formOption = reactive({
+  readonly: false, //用于控制整个表单是否只读
+  disabled: false,
+  labelAlign: "top",
+  scroll: true,
+  labelWidth: "62pk",
+  // hiddenSubmitBtn: true,
+});
+const formConfig = ref([
+  {
+    type: "cascader",
+    label: proxy.t('user.deptName'),
+    prop: "deptId",
+    itemType: "common",
+    showPicker: false,
+    data: [],
+    fieldNames: {
+      text: "deptName",
+      value: "deptId",
+      children: "children",
+    },
+  },
+  {
+    type: "input",
+    itemType: "text",
+    label: proxy.t('user.nickName'),
+    prop: "nickName",
+    clearable: true,
+  },
+  
+  {
+    type: "input",
+    itemType: "text",
+    label: proxy.t('user.salesmanCode'),
+    prop: "userCode",
+    clearable: true,
+  },
+  
+]);
+const rules = {
+  deptId: [{ required: true, message: proxy.t('user.deptNameCanNotBeEmpty'), }],
+  nickName: [{ required: true, message: proxy.t('user.nameCanNotBeEmpty'), }],
+  userName: [{ required: true, message: proxy.t('user.userNameCanNotBeEmpty'), }],
+  password: [{ required: true, message: proxy.t('user.passwordCanNotBeEmpty'), }],
+  roleIds: [{ required: true, message: proxy.t('user.roleCanNotBeEmpty'),}],
+  phonenumber: [{ required: true, message: proxy.t('user.phoneCanNotBeEmpty'), }],
+};
+const unitList = ref([]);
+
+const getUserList = () => {
+  proxy
+    .get("/tenantRole/list", {
+      pageNum: 1,
+      pageSize: 10000,
+      tenantId: getUserInfo().tenantId,
+    })
+    .then((message) => {
+      formConfig.value[5].data = message.rows.map((item) => {
+        return {
+          text: item.roleName,
+          value: item.roleId,
+        };
+      });
+    });
+};
+
+getUserList();
+const fileList = ref([]);
+const onOversize = () => {
+  showToast("文件大小不能超过 5MB");
+};
+const onClickLeft = () => history.back();
+const onSubmit = () => {
+  formData.data.tenantId = getUserInfo().tenantId
+  formData.data.password = null
+  proxy
+    .post("/system/user", formData.data, route.query.id ? "PUT" : "PUT")
+    .then(() => {
+      showSuccessToast(route.query.id ? proxy.t('common.modifySuccess') : proxy.t('common.modifySuccess'))
+      setTimeout(() => {
+        history.back();
+      }, 500);
+    });
+};
+const treeToList = (arr) => {
+  let res = []; // 用于存储递归结果(扁平数据)
+  // 递归函数
+  let fn = (source) => {
+    source.forEach((el) => {
+      res.push(el);
+      el.children && el.children.length > 0 ? fn(el.children) : ""; // 子级递归
+    });
+  };
+  fn(arr);
+  return res;
+};
+
+const getTree = () => {
+  proxy
+    .get("/tenantDept/list", { tenantId: getUserInfo().tenantId })
+    .then((res) => {
+      formConfig.value[0].data = handleTree(res.data, "deptId");
+    })
+    .catch((err) => {});
+};
+getTree();
+onMounted(() => {
+  if (route.query.userId) {
+    console.log(route.query);
+    proxy.get(`/tenantUser/${route.query.userId}`).then((res) => {
+      res.data.password = ""
+      formData.data = {
+        ...res.data,
+        roleIds:res.roleIds
+      }
+    });
+    
+  } else {
+    
+  }
+});
+</script>

+ 149 - 0
src/views/system/salesman/index.vue

@@ -0,0 +1,149 @@
+<template>
+	<van-nav-bar
+		:title="$t('user.salesmanManagement')"
+		left-text=""
+		left-arrow
+		@click-left="onClickLeft"
+		@click-right="onClickRight"
+	>
+		
+	</van-nav-bar>
+	<van-search
+		v-model="req.keyword"
+		:placeholder="$t('common.pleaseEnterKeywords')"
+		@search="onRefresh"
+	/>
+	<van-pull-refresh v-model="loading" @refresh="onRefresh">
+		<div class="list">
+			<van-list
+				v-model:loading="loading"
+				:finished="finished"
+				:finished-text="$t('common.noMore')"
+				@load="onLoad"
+				style="margin-bottom: 60px"
+			>
+				<commonList
+					:data="listData"
+					@onClick="toDtl"
+					:config="listConfig"
+				></commonList>
+			</van-list>
+		</div>
+	</van-pull-refresh>
+</template>
+<script setup>
+import { ref, getCurrentInstance } from 'vue'
+import commonList from '@/components/common-list.vue'
+import { useRoute } from 'vue-router'
+import { getUserInfo } from '@/utils/auth'
+const loading = ref(false)
+const router = useRoute()
+const req = ref({
+	pageNum: 1,
+	keyword: null,
+	definition: '1',
+    tenantId: getUserInfo().tenantId
+})
+const finished = ref(false)
+const proxy = getCurrentInstance().proxy
+const listData = ref([])
+const listConfig = ref([
+	{
+		label: proxy.t('user.belongDept'),
+		prop: 'deptName',
+	},
+	{
+		label: proxy.t('user.employeeName'),
+		prop: 'nickName',
+	},
+	{
+		label: proxy.t('user.businessCode'),
+		prop: 'userCode',
+	},
+])
+//车间类型
+const typeList = ref([
+	{
+		label: proxy.t('user.ordinaryProductionLine'),
+		value: '1',
+	},
+	{
+		label: proxy.t('user.semiAutomaticProductionLine'),
+		value: '2',
+	},
+	{
+		label: proxy.t('user.automaticProductionLine'),
+		value: '3',
+	},
+])
+const onRefresh = () => {
+	req.value.pageNum = 1
+	finished.value = false
+	getList('refresh')
+}
+const onLoad = () => {
+	
+}
+const onClickLeft = () => proxy.$router.push('/main/working')
+const onClickRight = () => {
+	proxy.$router.push({
+		path: 'userAdd',
+		query: {
+			type: 'add',
+		},
+	})
+}
+proxy.uploadDdRightBtn(onClickRight,proxy.t('common.add'))
+const toDtl = (row) => {
+	proxy.$router.push({
+		path: 'salesmanAdd',
+		query: {
+			...row,
+			type: 'edit',
+		},
+	})
+}
+const treeToList = (arr) => {
+	let res = [] // 用于存储递归结果(扁平数据)
+	// 递归函数
+	let fn = (source) => {
+		source.forEach((el) => {
+			res.push(el)
+			el.children && el.children.length > 0 ? fn(el.children) : '' // 子级递归
+		})
+	}
+	fn(arr)
+	return res
+}
+const getList = (type) => {
+	loading.value = true
+	proxy
+		.get('/tenantUser/list', req.value)
+		.then((res) => {
+			listData.value =
+				type === 'refresh'
+					? res.rows
+					: listData.value.concat(res.rows)
+			if (req.value.pageNum * 10 >= res.total) {
+				finished.value = true
+			}
+			req.value.pageNum++
+			loading.value = false
+			listData.value = listData.value.map((item) => {
+				item.deptName = item.dept ? item.dept.deptName : ''
+				return item
+			})
+			console.log(listData.value)
+		})
+		.catch((err) => {
+			loading.value = false
+		})
+}
+getList()
+</script>
+
+<style lang="scss" scoped>
+.list {
+	min-height: 70vh;
+}
+</style>

+ 113 - 44
src/views/working/index.vue

@@ -1,20 +1,42 @@
 <template>
   <div class="working">
-    <van-swipe class="my-swipe" indicator-color="white">
+    <van-search
+      v-model="keyword"
+      :placeholder="$t('common.pleaseEnterKeywords')"
+      @update:model-value="searchFn"
+    />
+    <van-swipe class="my-swipe" indicator-color="white" style="margin-top:10px">
       <van-swipe-item @click="toWinfaster">
         <img src="../../assets/images/banner1.png" alt="">
       </van-swipe-item>
       <van-swipe-item>2</van-swipe-item>
-
     </van-swipe>
-    <div class="card" v-for="i in routerData" :key="i.path">
+    
+    <div class="card" v-if="keyword">
+      <div class="title">{{$t('common.searchResults')}}</div>
+      <ul>
+        <li v-for="j in searchList" :key="j.path" @click="toRouter(j)" :style="colorRgb(j.background || '#0084FF',0.1)">
+          <div class="icon"  :style="colorRgb(j.background || '#0084FF',1)">
+            <i class="iconfont" :class="'icon-' + j.meta.icon" ></i>
+            
+          </div>
+          
+          <div class="yuan" :style="colorRgb(j.background || '#0084FF',0.2)"></div>
+          <div class="text">{{ j.meta.title }}</div>
+        </li>
+      </ul>
+      <h2 style="text-align:center;padding-bottom:40px">{{$t('common.noMatchingData')}}</h2>
+    </div>
+    <div class="card" v-for="i in routerData" :key="i.path" v-else>
       <div class="title">{{ i.meta.title }}</div>
       <ul>
-        <li v-for="j in i.children" :key="j.path" @click="toRouter(j)">
-          <div class="icon"  :style="`background:${j.background ? j.background : '#1989fa'};color:${j.color ? j.color : '#fff'}`">
+        <li v-for="j in i.children" :key="j.path" @click="toRouter(j)" :style="colorRgb(j.background || '#0084FF',0.1)">
+          <div class="icon"  :style="colorRgb(j.background || '#0084FF',1)">
             <i class="iconfont" :class="'icon-' + j.meta.icon" ></i>
             
           </div>
+          
+          <div class="yuan" :style="colorRgb(j.background || '#0084FF',0.2)"></div>
           <div class="text">{{ j.meta.title }}</div>
         </li>
       </ul>
@@ -39,39 +61,57 @@ const getRouter = () => {
     
   });
 };
+const keyword = ref(null);
+const searchList = ref([]);
+const searchFn = (text) => {
+  searchList.value = [];
+  if(!text) return
+  //在routerData中查找
+  routerData.value.map(item => {
+    item.children.map(item => {
+      if(item.meta.title.indexOf(text) > -1){
+        searchList.value.push(item)
+      }
+    })
+    
+  })
+  console.log(searchList)
+};
 getRouter();
 const toWinfaster = () => {
   proxy.$router.push({
     path: "/main/iframWinfaster",
   });
 };
-const toRouter = (item) => {
-  proxy.$router.push({
-    path: item.path,
-  });
-};
-const handleGo = (type) => {
-  if (type === 1) {
-    proxy.$router.push({
-      path: "/purchase-sales/manualOutbound",
-    });
-  }
-  if (type === 2) {
-    proxy.$router.push({
-      path: "/purchase-sales/manualInbound",
-    });
-  }
-  if (type === 3) {
-    proxy.$router.push({
-      path: "/purchase-sales/manualOutbound",
-    });
-  }
-  if (type === 4) {
-    proxy.$router.push({
-      path: "warehouseConfig",
-    });
+//16进制转rgba的函数
+const colorRgb = (sColor, alpha) => {
+  var reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/;
+  var sColor = sColor.toLowerCase();
+  if (sColor && reg.test(sColor)) {
+    if (sColor.length === 4) {
+      var sColorNew = "#";
+      for (var i = 1; i < 4; i += 1) {
+        sColorNew += sColor
+          .slice(i, i + 1)
+          .concat(sColor.slice(i, i + 1));
+      }
+      sColor = sColorNew;
+    }
+    //处理六位的颜色值
+    var sColorChange = [];
+    for (var i = 1; i < 7; i += 2) {
+      sColorChange.push(parseInt("0x" + sColor.slice(i, i + 2)));
+    }
+    return (
+      "background:rgba(" + sColorChange.join(",") + "," + alpha + ")"
+    );
+  } else {
+    return sColor;
   }
 };
+const toRouter = (item) => {
+  proxy.$router.push(item.path);
+};
 </script>
 <style lang="scss" scoped>
 .working {
@@ -124,29 +164,58 @@ const handleGo = (type) => {
     ul {
       display: flex;
       flex-wrap: wrap;
-      padding-bottom: 30px;
+      padding: 0 8px 12px;
 
       li {
-        width: 25%;
-        text-align: center;
-        margin-top: 10px;
+        width: 23%;
+        
+        padding: 12px;
+        margin: 10px 1% 0;
+        box-sizing: border-box;
+        background: rgba(0, 132, 255, 0.1);
+        border-radius: 12px;
+        position: relative;
         .icon {
-          height: 40px;
-          width: 40px;
-          margin: 0 auto;
-          background: #1989fa;
-          line-height: 40px;
-          border-radius: 5px;
+          height: 28px;
+          width: 28px;
+          text-align: center;
+          background: rgba(0, 132, 255, 1);
+          line-height: 28px;
+          border-radius: 8px;
           color: #fff;
-          font-size: 20px;
+          font-size: 14px;
+          z-index: 2;
+          position: relative;
           .iconfont{
-            font-size: 20px;
+            font-size: 14px;
           }
         }
         .text {
           font-size: 12px;
-          height: 24px;
-          line-height: 24px;
+          height: 26px;
+          line-height: 14px;
+          margin-top:12px;
+          color: #333;
+          font-weight: bold;
+          position: relative;
+          z-index: 1;
+          //文字两行多余省略
+          overflow: hidden;
+          text-overflow: ellipsis;
+          display: -webkit-box;
+          -webkit-line-clamp: 2;
+          -webkit-box-orient: vertical;
+          
+        }
+        .yuan{
+          width: 20px;
+          height: 20px;
+          border-radius: 50%;
+          background: rgba(0, 132, 255, 0.2);
+          position: absolute;
+          left: 25px;
+          top: 25px;
+          z-index: 0;
         }
       }
     }

Certains fichiers n'ont pas été affichés car il y a eu trop de fichiers modifiés dans ce diff