Przeglądaj źródła

待采购,已采购模块。 列表组件新增多选功能和根据某个key自动过滤功能

asd26269546 2 lat temu
rodzic
commit
37d6009be1

+ 110 - 54
src/components/common-list.vue

@@ -1,64 +1,120 @@
 <template>
-  <div class="common-list">
-    <ul>
-      <li v-for="i in data" :key="i.id" @click="listCk(i)">
-        <!-- <div class="left-box">
-                    <van-icon name="location-o" />
-                </div> -->
-        <div class="center-content" style="line-height: 24px">
-          <div v-for="j in config" :key="j.prop">
-            <span>{{ j.label }}:</span>{{ i[j.prop] }}
-          </div>
-        </div>
-        <div class="more-box" v-if="showMore">
-          <van-icon name="arrow" />
-        </div>
-      </li>
-    </ul>
-  </div>
+	<div class="common-list">
+		<ul>
+			<li v-for="i in listData" :key="i.id">
+				<div
+					class="left-box"
+					style="margin-right: 20px"
+					v-if="isCheckbox"
+				>
+					<van-checkbox
+						v-model="i.checked"
+						icon-size="15px"
+						shape="square"
+						@change='listCheck'
+						:disabled="optionalValue ? (optionalValue != i[optionalKey]) : false"
+					></van-checkbox>
+				</div>
+				<div
+					class="center-content"
+					style="line-height: 24px"
+					@click="listCk(i)"
+				>
+					<div v-for="j in config" :key="j.prop">
+						<span>{{ j.label }}:</span>{{ i[j.prop] }}
+					</div>
+				</div>
+				<div class="more-box" v-if="showMore" @click="listCk(i)">
+					<van-icon name="arrow" />
+				</div>
+			</li>
+		</ul>
+	</div>
 </template>
 <script setup>
-import { ref, getCurrentInstance, onMounted, defineProps } from "vue";
-const proxy = getCurrentInstance().proxy;
+import { ref, getCurrentInstance, onMounted, defineProps, watch } from 'vue'
+const proxy = getCurrentInstance().proxy
 defineProps({
-  data: {
-    type: Array,
-    default: [],
-  },
-  config: {
-    type: Object,
-    default: [],
-  },
-  showMore: {
-    type: Boolean,
-    default: true,
-  },
-});
-
+	data: {
+		type: Array,
+		default: [],
+	},
+	config: {
+		type: Object,
+		default: [],
+	},
+	showMore: {
+		type: Boolean,
+		default: true,
+	},
+	isCheckbox: {
+		type: Boolean,
+		default: false,
+	},
+	optionalKey: {
+		type: String,
+		default: null,
+	},
+})
+let listData = ref([])
+let checkList = []
+watch(
+	() => proxy.data,
+	(newVal) => {
+		listData.value = newVal.map((i) => {
+			//判断是否有选中的
+			if (checkList.length > 0) {
+				checkList.map((j) => {
+					if (i.id == j.id) {
+						i.checked = true
+					}
+				})
+			}
+			return i
+		})
+	}
+)
+const optionalValue = ref(null)
+const listCheck = () => {
+	checkList = []
+	listData.value.map((i) => {
+		if (i.checked) {
+			checkList.push(i)
+			if(!optionalValue.value) {
+				optionalValue.value = i[proxy.optionalKey]
+			}
+		}
+	})
+	if(checkList.length == 0) {
+		optionalValue.value = null
+	}
+	proxy.$emit('onCheck', checkList)
+}
 const listCk = (item) => {
-  proxy.$emit("onClick", item);
-};
+	
+	proxy.$emit('onClick', item)
+}
 </script>
 <style lang="scss">
 .common-list {
-  ul {
-    margin-top: 10px;
-    li {
-      list-style: none;
-      position: relative;
-      display: flex;
-      box-sizing: border-box;
-      align-items: center;
-      justify-content: space-between;
-      padding: 12px 16px;
-      background: #fff;
-      border-bottom: 1px solid #f1f1f1;
-      .center-content {
-        flex: 1;
-      }
-      .left-box {
-      }
-    }
-  }
+	ul {
+		margin-top: 10px;
+		li {
+			list-style: none;
+			position: relative;
+			display: flex;
+			box-sizing: border-box;
+			align-items: center;
+			justify-content: space-between;
+			padding: 12px 16px;
+			background: #fff;
+			border-bottom: 1px solid #f1f1f1;
+			.center-content {
+				flex: 1;
+			}
+			.left-box {
+			}
+		}
+	}
 }
 </style>

+ 22 - 0
src/router/index.js

@@ -92,6 +92,28 @@ const routes = [{
 				name: '申购新增',
 				component: () => import('../views/procurementManagement/subscribe/add.vue')
 			},
+			{
+				path: 'procureList',
+				name: '待采购',
+				component: () => import('../views/procurementManagement/procureList/index.vue')
+			},
+			{
+				path: 'procureListAdd',
+				name: '采购提交',
+				component: () => import('../views/procurementManagement/procureList/add.vue')
+			},
+			{
+				path: 'purchased',
+				name: '已采购',
+				component: () => import('../views/procurementManagement/purchased/index.vue')
+			},
+			{
+				path: 'purchasedAdd',
+				name: '已采购详情',
+				component: () => import('../views/procurementManagement/purchased/add.vue')
+			},
+			
+			
 			//仓库模块
 			{
 				path: 'warehouseConfig',

+ 27 - 0
src/utils/auth.js

@@ -18,3 +18,30 @@ export function setToken(token) {
 export function removeToken() {
     return localStorage.remove('token')
 }
+
+//时间格式化方法
+export function formatDate(date, fmt) {
+    if (/(y+)/.test(fmt)) {
+        fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length));
+    }
+    let o = {
+        'M+': date.getMonth() + 1,
+        'd+': date.getDate(),
+        'h+': date.getHours(),
+        'm+': date.getMinutes(),
+        's+': date.getSeconds()
+    };
+    for (let k in o) {
+        if (new RegExp(`(${k})`).test(fmt)) {
+            let str = o[k] + '';
+            fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1) ? str : padLeftZero(str));
+        }
+    }
+    return fmt;
+}
+
+function padLeftZero(str) {
+    return ('00' + str).substr(str.length);
+}
+
+

+ 5 - 2
src/utils/axios.js

@@ -3,7 +3,7 @@ import axios from 'axios'
 import errorCode from '@/utils/errorCode'
 import { tansParams, blobValidate } from '@/utils/ruoyi'
 import cache from '@/utils/cache'
-import { showLoadingToast, closeToast,showNotify  } from 'vant';
+import { showLoadingToast, closeToast,showNotify,showFailToast  } from 'vant';
 import { getToken } from '@/utils/auth'
 // 是否显示重新登录
 export let isRelogin = { show: false };
@@ -87,7 +87,10 @@ service.interceptors.response.use(res => {
     }
     return Promise.reject('无效的会话,或者会话已过期,请重新登录。')
   } else if (code === 500) {
-    showNotify({ type: 'danger', message: msg });
+    
+    setTimeout(() => {
+      showFailToast(msg);
+    }, 500);
     //ElMessage({ message: msg, type: 'error' })
     return Promise.reject(new Error(msg))
   } else if (code === 601) {

+ 2 - 1
src/views/equipment/warpKnitting.vue

@@ -1,5 +1,5 @@
 <template>
-	<van-nav-bar title="标题" left-arrow />
+	<van-nav-bar title="标题" left-arrow @click-left="onClickLeft" />
 	<van-pull-refresh v-model="loading" @refresh="onRefresh">
 		<div class="warpKnitting">
 			<div class="stat">
@@ -153,6 +153,7 @@ const getDtl = () => {
 	)
 	
 }
+const onClickLeft = () => history.back();
 getDtl()
 onMounted(() => {
 	const myChart = echarts.init(document.getElementById('myCharts'))

+ 3 - 3
src/views/main.vue

@@ -2,16 +2,16 @@
 	<div class="main">
 		<div class="footer">
 			<van-tabbar v-model="tabType">
-				<van-tabbar-item icon="home-o" to="/main/equipment">消息</van-tabbar-item>
+				<!-- <van-tabbar-item icon="home-o" to="/main/equipment">消息</van-tabbar-item> -->
 				<van-tabbar-item icon="search" to="/main/working">工作台</van-tabbar-item>
 				<van-tabbar-item
 					icon="friends-o"
 					:to="tenantId == 'xmhjc' ? '/main/xiamenList' : '/main/equipment'"
 				>物联网</van-tabbar-item>
-				<van-tabbar-item
+				<!-- <van-tabbar-item
 					icon="setting-o"
 					to="/setting"
-				>我的</van-tabbar-item>
+				>我的</van-tabbar-item> -->
 			</van-tabbar>
 		</div>
 	</div>

+ 4 - 4
src/views/procurementManagement/priceConfig/edit.vue

@@ -5,12 +5,12 @@
         <van-form @submit="editSubmit" label-align="top" style="margin-top: 20px">
             <van-cell-group inset>
                 <van-field v-model="formData.supplierInfoName" is-link readonly label="供应商" placeholder="选择供应商"
-                    @click="typeModal = true" :rules="[{ required: true, message: '供应商不能为空' }]" required />
+                    />
                 <van-popup v-model:show="typeModal" round position="bottom">
                     <van-picker :columns="columns" @cancel="typeModal = false" @confirm="onConfirm" />
                 </van-popup>
                 <van-field v-model="formData.productInfoName" is-link readonly label="物品名称" placeholder="选择物品名称"
-                    @click="handleSelect(index)" :rules="[{ required: true, message: '物品名称不能为空' }]" required
+                   
                     v-if="route.query.id" />
 
                 <van-field v-model="formData.price" label="供应单价" placeholder="请输入供应单价"
@@ -126,8 +126,8 @@ const editSubmit = () => {
 onMounted(() => {
     console.log(route.query)
     formData.value = {
-        supplierInfoName: route.query.supplierInfoName,
-        productInfoName: route.query.productInfoName,
+        supplierInfoName: route.query.supplierName,
+        productInfoName: route.query.productClassifyName,
         id: route.query.id,
         supplierInfoId: route.query.supplierInfoId,
         productInfoId: route.query.productInfoId,

+ 364 - 0
src/views/procurementManagement/procureList/add.vue

@@ -0,0 +1,364 @@
+<template>
+	<div class="form" style="padding-bottom: 60px">
+		<van-nav-bar
+			title="待采购"
+			left-text="返回"
+			left-arrow
+			@click-left="onClickLeft"
+		>
+		</van-nav-bar>
+		<van-form @submit="onSubmit" label-align="top" style="margin-top: 20px">
+			<van-cell-group inset>
+				<van-field
+					v-model="formData.deptName"
+					is-link
+					readonly
+					label="申购部门"
+					placeholder="选择申购部门"
+					:rules="[{ required: true, message: '申购部门不能为空' }]"
+					:readonly="true"
+					required
+				/>
+				<van-field
+					v-model="formData.purchaseName"
+					type="text"
+					name="申购人名称"
+					label="申购人名称"
+					placeholder="请填写申购人名称"
+					:rules="[{ required: true, message: '申购人名称不能为空' }]"
+                    required
+					:readonly="true"
+				/>
+				<van-field
+					v-model="formData.purchaseTime"
+					is-link
+					readonly
+					name="datePicker"
+					label="申购时间"
+					placeholder="点击选择时间"
+					
+					
+					:rules="[{ required: true, message: '申购时间不能为空' }]"
+                    required
+					:readonly="true"
+				/>
+				<van-popup v-model:show="timePicker" position="bottom">
+					<van-date-picker
+						@confirm="timeOnConfirm"
+						@cancel="timePicker = false"
+					/>
+				</van-popup>
+				<van-field
+					v-model="formData.supplyName"
+					is-link
+					readonly
+					label="供应商"
+					placeholder="选择供应商"
+					@click=" typeModal = true"
+					:rules="[{ required: true, message: '供应商不能为空' }]"
+					required
+				/>
+				<van-popup v-model:show="typeModal" position="bottom">
+					<van-picker
+						title="标题"
+						:columns="supplyList"
+						@confirm="onConfirm"
+						@cancel="typeModal = false"
+					/>
+				</van-popup>
+				<van-field
+					v-model="formData.purchaseContent"
+					type="textarea"
+					name="申购说明"
+					label="申购说明"
+					placeholder="请填写申购说明"
+					:rules="[{ required: true, message: '申购说明不能为空' }]"
+                    required
+					rows="3"
+				/>
+			</van-cell-group>
+
+			<!-- 明细列表 -->
+			<div
+				v-for="(item, index) in formData.purchaseDetailList"
+				:key="index"
+			>
+				<div class="commons-delete">
+					<div class="title">明细{{ index + 1 }}</div>
+					<!-- <div
+						class="delete"
+						@click.native="handleDel(index)"
+						v-if="!route.query.id"
+					>
+						<van-icon name="cross" />
+					</div> -->
+				</div>
+				<van-cell-group inset>
+					<van-field
+						v-model="
+							formData.purchaseDetailList[index].productName
+						"
+						is-link
+						readonly
+						label="申购产品"
+						placeholder="选择申购产品"
+						:readonly="true"
+						
+						:rules="[
+							{ required: true, message: '申购产品不能为空' },
+						]"
+						required
+					/>
+					<van-field
+						v-model="formData.purchaseDetailList[index].count2"
+						label="数量"
+						placeholder="请输入数量"
+						:rules="[{ required: true, message: '数量不能为空' }]"
+						required
+                        type="number"
+						:readonly="true"
+					/>
+
+					<van-field
+						v-model="formData.purchaseDetailList[index].count"
+						name="本次采购"
+						label="本次采购"
+						placeholder="请输入"
+						@change='changePrice(index)'
+						:rules="[{ required: true, message: '本次采购不能为空' }]"
+						required
+						type="number"
+					/>
+					<van-field
+						v-model="formData.purchaseDetailList[index].price"
+						name="单价"
+						label="单价"
+						@change='changePrice(index)'
+						placeholder="请输入"
+						:rules="[{ required: true, message: '单价不能为空' }]"
+						required
+						type="number"
+					/>
+					<van-field
+						v-model="formData.purchaseDetailList[index].amount"
+						name="总价"
+						label="总价"
+						placeholder="根据本次采购和单价自动计算"
+						:readonly="true"
+						type="number"
+					/>
+				</van-cell-group>
+				
+			</div>
+			<van-field
+				style="margin-top:16px"
+				v-model="formData.amount"
+				name="总价"
+				label="总价"
+				placeholder="所有明细的金额合计"
+				:readonly="true"
+				type="number"
+			/>
+			<van-popup v-model:show="typeModalOne" round position="bottom">
+				<van-picker
+					:columns="columnsOne"
+					@cancel="typeModalOne = false"
+					@confirm="(data) => onConfirmOne(data)"
+				/>
+			</van-popup>
+			<div style="margin: 16px" v-if="!route.query.id">
+				<van-button round block type="primary" native-type="submit">
+					提交
+				</van-button>
+			</div>
+		</van-form>
+	</div>
+</template>
+
+<script setup>
+import { ref, getCurrentInstance, onMounted } from 'vue'
+import { showSuccessToast, showFailToast } from 'vant'
+import { useRoute } from 'vue-router'
+import { setUserInfo,setToken, getUserInfo,formatDate } from '@/utils/auth';
+const proxy = getCurrentInstance().proxy
+const route = useRoute()
+const typeModal = ref(false)
+const typeModalOne = ref(false)
+let selectIndex = ref(null)
+const timePicker = ref(false)
+const userInfo = getUserInfo()
+const formData = ref({
+	deptName: userInfo.dept.deptName,
+	purchaseName: userInfo.nickName,
+	purchaseTime: formatDate(new Date(), 'yyyy-MM-dd'),
+	supplyId: '',
+	purchaseContent: '',
+	amount: '',
+	purchaseDetailList: [],
+})
+const handleAddRow = () => {
+	formData.value.subscribeDetailList.push({
+		bussinessId: '',
+		bussinessName: '',
+		name: '',
+		quantity: '',
+        content:"",
+        count:"",
+	})
+}
+
+const supplyList = ref([])
+
+const timeOnConfirm = ({ selectedValues }) => {
+	formData.value.subcribeTime = selectedValues.join('-')
+	timePicker.value = false
+}
+
+const getDict = () => {
+	
+	proxy
+		.post('/supplierPrice/page', { pageNum: 1, pageSize: 9999 })
+		.then((res) => {
+			supplyList.value = res.data.rows.map((item) => {
+				return {
+					...item,
+					text: item.supplierName,
+					value: item.supplierInfoId,
+				}
+			})
+			console.log(supplyList,12312312312312)
+		})
+
+	proxy
+		.post('/productInfo/page', { pageNum: 1, pageSize: 9999 })
+		.then((res) => {
+			columnsOne.value = res.data.rows.map((item) => {
+				return {
+					...item,
+					text: item.name,
+					value: item.id,
+				}
+			})
+		})
+}
+
+//总价保留两位小数
+const changePrice = (index) => {
+	formData.value.purchaseDetailList[index].amount = (
+		formData.value.purchaseDetailList[index].count *
+		formData.value.purchaseDetailList[index].price
+	).toFixed(2)
+	formData.value.amount = formData.value.purchaseDetailList.reduce(
+		(total, item) => {
+			return total + Number(item.amount)
+		},
+		0
+	)
+}
+
+const getDetails = (id) => {
+	proxy.post('/subscribe/detail', { id:id }).then((res) => {
+		res.data.subscribeDetailList.map((item) => {
+			columnsOne.value.map((itemOne) => {
+				if(itemOne.value === item.bussinessId) {
+					item.bussinessName = itemOne.name
+				}
+			})
+			
+		})
+		formData.value = res.data
+
+		
+		console.log(formData.value)
+	})
+}
+
+const columns = ref([])
+const columnsOne = ref([])
+const submitType = ref('add')
+
+const onConfirm = ({ selectedOptions }) => {
+	formData.value.supplyId = selectedOptions[0].value
+	formData.value.supplyName = selectedOptions[0].text
+	typeModal.value = false
+}
+
+const onConfirmOne = ({ selectedOptions }) => {
+	formData.value.subscribeDetailList[selectIndex.value].bussinessId =
+		selectedOptions[0].value
+	formData.value.subscribeDetailList[selectIndex.value].bussinessName =
+		selectedOptions[0].text
+	typeModalOne.value = false
+}
+
+const handleSelect = (index) => {
+	if(submitType.value === 'edit') return
+	selectIndex.value = index
+	typeModalOne.value = true
+}
+
+const handleDel = (index) => {
+	formData.value.subscribeDetailList.splice(index, 1)
+}
+
+const onClickLeft = () => history.back()
+
+const onSubmit = () => {
+	proxy.post('/flowProcess/initiate', {
+		flowKey: 'purchase_flow',
+		data:formData.value,
+		remark:null,
+	}).then(
+		(res) => {
+			setTimeout(() => {
+				showSuccessToast('采购申请成功')
+				proxy.$router.push('/main/procureList')
+			}, 100)
+		},
+		(err) => {
+			return showFailToast(err.message)
+		}
+	)
+}
+const getDtl = (query) => {
+    proxy
+        .post('/subscribeDetail/detail', { ids: JSON.parse(query.ids) })
+        .then((res) => {
+            formData.value.purchaseDetailList = res.data.map((item) => {
+				return {
+					
+					bussinessId: item.bussinessId,
+					productName: item.productName,
+					count2: item.count,
+					subscribeDetailId: item.id,
+					count:null,
+					content:null,
+					price:null,
+					amount:null,
+				}
+			})
+        })
+}
+onMounted(() => {
+    console.log(route)
+    getDtl(route.query)
+	getDict()
+})
+</script>
+<style lang="scss" scoped>
+.row {
+	display: flex;
+	padding: 5px 15px;
+	justify-content: space-between;
+	align-items: center;
+	color: #999999;
+	.title {
+		flex: 1;
+	}
+	.delete {
+		width: 20px;
+		cursor: pointer;
+		text-align: center;
+	}
+}
+</style>

+ 135 - 0
src/views/procurementManagement/procureList/index.vue

@@ -0,0 +1,135 @@
+<template>
+	<van-nav-bar
+		title="待采购"
+		left-text=""
+		left-arrow
+		@click-left="onClickLeft"
+		@click-right="onClickRight"
+	>
+		<template #right> 采购 </template>
+	</van-nav-bar>
+	<van-search
+		v-model="req.keyword"
+		placeholder="请输入搜索关键词"
+		@search="onRefresh"
+	/>
+	<van-pull-refresh v-model="loading" @refresh="onRefresh">
+		<div class="list">
+			<van-list
+				v-model:loading="loading"
+				:finished="finished"
+				finished-text="没有更多了"
+				@load="onLoad"
+				style="margin-bottom: 60px"
+			>
+				<commonList
+					:data="listData"
+					@onClick="toDtl"
+					:config="listConfig"
+					:isCheckbox="true"
+					@onCheck="onCkeckbox"
+					optionalKey='subcribeId'
+				></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'
+const loading = ref(false)
+const router = useRoute()
+const req = ref({
+	pageNum: 1,
+	type: '1',
+	keyword: null,
+})
+const finished = ref(false)
+const proxy = getCurrentInstance().proxy
+const listData = ref([])
+
+const listConfig = ref([
+	{
+		label: '申购单号',
+		prop: 'subscribeCode',
+	},
+	{
+		label: '物品名称',
+		prop: 'productName',
+	},
+	{
+		label: '申购数量',
+		prop: 'count',
+	},
+	{
+		label: '已采购',
+		prop: 'count',
+	},
+])
+const onRefresh = () => {
+	req.value.pageNum = 1
+	finished.value = false
+	getList('refresh')
+}
+const onLoad = () => {
+	getList()
+}
+let ids = []
+
+const onCkeckbox = (row) => {
+	ids = []
+	row.map((i) => {
+		ids.push(i.id)
+	})
+}
+
+const onClickLeft = () => proxy.$router.push('/main/working')
+
+const onClickRight = () => {
+	proxy.$router.push({
+		path: 'procureListAdd',
+		query: {
+			ids: JSON.stringify(ids),
+		},
+	})
+}
+
+const toDtl = (row) => {
+	proxy.$router.push({
+		path: 'procureListAdd',
+		query: {
+			ids: JSON.stringify([row.id]),
+			
+		},
+	})
+}
+
+const getList = (type) => {
+	loading.value = true
+	proxy
+		.post('/subscribeDetail/page', req.value)
+		.then((res) => {
+			console.log(req.value)
+			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
+		})
+}
+getList()
+</script>
+
+<style lang="scss" scoped>
+.list {
+	min-height: 70vh;
+}
+</style>

+ 357 - 0
src/views/procurementManagement/purchased/add.vue

@@ -0,0 +1,357 @@
+<template>
+	<div class="form" style="padding-bottom: 60px">
+		<van-nav-bar
+			title="带采购"
+			left-text="返回"
+			left-arrow
+			@click-left="onClickLeft"
+		>
+		</van-nav-bar>
+		<van-form @submit="onSubmit" label-align="top" style="margin-top: 20px">
+			<van-cell-group inset>
+				<van-field
+					v-model="formData.deptName"
+					is-link
+					readonly
+					label="申购部门"
+					placeholder="选择申购部门"
+					:rules="[{ required: true, message: '申购部门不能为空' }]"
+					:readonly="true"
+					required
+				/>
+				<van-field
+					v-model="formData.purchaseName"
+					type="text"
+					name="申购人名称"
+					label="申购人名称"
+					placeholder="请填写申购人名称"
+					:rules="[{ required: true, message: '申购人名称不能为空' }]"
+                    required
+					:readonly="true"
+				/>
+				<van-field
+					v-model="formData.purchaseTime"
+					is-link
+					readonly
+					name="datePicker"
+					label="申购时间"
+					placeholder="点击选择时间"
+					
+					
+					:rules="[{ required: true, message: '申购时间不能为空' }]"
+                    required
+					:readonly="true"
+				/>
+				<van-popup v-model:show="timePicker" position="bottom">
+					<van-date-picker
+						@confirm="timeOnConfirm"
+						@cancel="timePicker = false"
+					/>
+				</van-popup>
+				<van-field
+					v-model="formData.supplyName"
+					is-link
+					readonly
+					label="供应商"
+					placeholder="选择供应商"
+					@click=" typeModal = true"
+					:rules="[{ required: true, message: '供应商不能为空' }]"
+					required
+				/>
+				<van-popup v-model:show="typeModal" position="bottom">
+					<van-picker
+						title="标题"
+						:columns="supplyList"
+						@confirm="onConfirm"
+						@cancel="typeModal = false"
+					/>
+				</van-popup>
+				<van-field
+					v-model="formData.purchaseContent"
+					type="textarea"
+					name="申购说明"
+					label="申购说明"
+					placeholder="请填写申购说明"
+					rows="3"
+				/>
+			</van-cell-group>
+
+			<!-- 明细列表 -->
+			<div
+				v-for="(item, index) in formData.purchaseDetailList"
+				:key="index"
+			>
+				<div class="commons-delete">
+					<div class="title">明细{{ index + 1 }}</div>
+					<div
+						class="delete"
+						@click.native="handleDel(index)"
+						v-if="!route.query.id"
+					>
+						<van-icon name="cross" />
+					</div>
+				</div>
+				<van-cell-group inset>
+					<van-field
+						v-model="
+							formData.purchaseDetailList[index].productName
+						"
+						is-link
+						readonly
+						label="申购产品"
+						placeholder="选择申购产品"
+						:readonly="true"
+						@click="handleSelect(index)"
+						:rules="[
+							{ required: true, message: '申购产品不能为空' },
+						]"
+						required
+					/>
+					
+
+					<van-field
+						v-model="formData.purchaseDetailList[index].count"
+						name="本次采购"
+						label="本次采购"
+						placeholder="请输入"
+						@change='changePrice(index)'
+						:rules="[{ required: true, message: '本次采购不能为空' }]"
+						required
+						type="number"
+					/>
+					<van-field
+						v-model="formData.purchaseDetailList[index].price"
+						name="单价"
+						label="单价"
+						@change='changePrice(index)'
+						placeholder="请输入"
+						:rules="[{ required: true, message: '单价不能为空' }]"
+						required
+						type="number"
+					/>
+					<van-field
+						v-model="formData.purchaseDetailList[index].amount"
+						name="总价"
+						label="总价"
+						placeholder="根据本次采购和单价自动计算"
+						:readonly="true"
+						type="number"
+					/>
+				</van-cell-group>
+				
+			</div>
+			<div class="commons-add-btn"  v-if="!route.query.id">
+				<van-button
+				icon="plus"
+				type="default"
+				
+				size="small"
+				style="margin-top: 10px"
+				block
+				@click="handleAddRow"
+				>添加明细</van-button
+				>
+			</div>
+			<van-field
+				style="margin-top:16px"
+				v-model="formData.amount"
+				name="总价"
+				label="总价"
+				placeholder="所有明细的金额合计"
+				:readonly="true"
+				type="number"
+			/>
+			<van-popup v-model:show="productModal" round position="bottom">
+				<van-picker
+					:columns="productData"
+					@cancel="productModal = false"
+					@confirm="(data) => onConfirmOne(data)"
+				/>
+			</van-popup>
+			<div style="margin: 16px" v-if="!route.query.id">
+				<van-button round block type="primary" native-type="submit">
+					提交
+				</van-button>
+			</div>
+		</van-form>
+	</div>
+</template>
+
+<script setup>
+import { ref, getCurrentInstance, onMounted } from 'vue'
+import { showSuccessToast, showFailToast } from 'vant'
+import { useRoute } from 'vue-router'
+import { setUserInfo,setToken, getUserInfo,formatDate } from '@/utils/auth';
+const proxy = getCurrentInstance().proxy
+const route = useRoute()
+const typeModal = ref(false)
+const productModal = ref(false)
+let selectIndex = ref(null)
+const timePicker = ref(false)
+const userInfo = getUserInfo()
+const formData = ref({
+	deptName: userInfo.dept.deptName,
+	purchaseName: userInfo.nickName,
+	purchaseTime: formatDate(new Date(), 'yyyy-MM-dd'),
+	supplyId: '',
+	purchaseContent: '',
+	amount: '',
+	purchaseDetailList: [],
+})
+const handleAddRow = () => {
+	formData.value.purchaseDetailList.push({
+		bussinessId: '',
+		bussinessName: '',
+		name: '',
+		quantity: '',
+        content:"",
+        count:"",
+	})
+}
+
+const supplyList = ref([])
+
+const timeOnConfirm = ({ selectedValues }) => {
+	formData.value.subcribeTime = selectedValues.join('-')
+	timePicker.value = false
+}
+
+const getDict = () => {
+	
+	proxy
+		.post('/supplierPrice/page', { pageNum: 1, pageSize: 9999 })
+		.then((res) => {
+			supplyList.value = res.data.rows.map((item) => {
+				return {
+					...item,
+					text: item.supplierName,
+					value: item.supplierInfoId,
+				}
+			})
+			console.log(supplyList,12312312312312)
+		})
+
+	proxy
+		.post('/productInfo/page', { pageNum: 1, pageSize: 9999 })
+		.then((res) => {
+			productData.value = res.data.rows.map((item) => {
+				return {
+					...item,
+					text: item.name,
+					value: item.id,
+				}
+			})
+		})
+}
+
+//总价保留两位小数
+const changePrice = (index) => {
+	formData.value.purchaseDetailList[index].amount = (
+		formData.value.purchaseDetailList[index].count *
+		formData.value.purchaseDetailList[index].price
+	).toFixed(2)
+	formData.value.amount = formData.value.purchaseDetailList.reduce(
+		(total, item) => {
+			return total + Number(item.amount)
+		},
+		0
+	)
+}
+
+const getDetails = (id) => {
+	proxy.post('/subscribe/detail', { id:id }).then((res) => {
+		res.data.subscribeDetailList.map((item) => {
+			productData.value.map((itemOne) => {
+				if(itemOne.value === item.bussinessId) {
+					item.bussinessName = itemOne.name
+				}
+			})
+			
+		})
+		formData.value = res.data
+
+		
+		console.log(formData.value)
+	})
+}
+
+const columns = ref([])
+const productData = ref([])
+const submitType = ref('add')
+
+const onConfirm = ({ selectedOptions }) => {
+	formData.value.supplyId = selectedOptions[0].value
+	formData.value.supplyName = selectedOptions[0].text
+	typeModal.value = false
+}
+
+const onConfirmOne = ({ selectedOptions }) => {
+	formData.value.purchaseDetailList[selectIndex.value].bussinessId =
+		selectedOptions[0].value
+	formData.value.purchaseDetailList[selectIndex.value].productName =
+		selectedOptions[0].text
+	productModal.value = false
+}
+
+const handleSelect = (index) => {
+	if(route.query.id) return
+	selectIndex.value = index
+	productModal.value = true
+}
+
+const handleDel = (index) => {
+	formData.value.subscribeDetailList.splice(index, 1)
+}
+
+const onClickLeft = () => history.back()
+
+const onSubmit = () => {
+	proxy.post('/flowProcess/initiate', {
+		flowKey: 'purchase_flow',
+		data:formData.value,
+		remark:null,
+	}).then(
+		(res) => {
+			setTimeout(() => {
+				showSuccessToast('采购申请成功')
+				proxy.$router.push('/main/purchased')
+			}, 100)
+		},
+		(err) => {
+			return showFailToast(err.message)
+		}
+	)
+}
+const getDtl = (query) => {
+    proxy
+        .post('/purchase/detail', { id: query.id })
+        .then((res) => {
+            console.log(res.data)
+			formData.value = res.data
+        })
+}
+onMounted(() => {
+    console.log(route)
+	if (route.query.id) {
+		getDtl(route.query)
+	}
+	getDict()
+})
+</script>
+<style lang="scss" scoped>
+.row {
+	display: flex;
+	padding: 5px 15px;
+	justify-content: space-between;
+	align-items: center;
+	color: #999999;
+	.title {
+		flex: 1;
+	}
+	.delete {
+		width: 20px;
+		cursor: pointer;
+		text-align: center;
+	}
+}
+</style>

+ 128 - 0
src/views/procurementManagement/purchased/index.vue

@@ -0,0 +1,128 @@
+<template>
+  <van-nav-bar
+    title="已采购"
+    left-text=""
+    left-arrow
+    @click-left="onClickLeft"
+    @click-right="onClickRight"
+  >
+    <template #right> 新增采购 </template>
+  </van-nav-bar>
+  <van-search
+    v-model="req.keyword"
+    placeholder="请输入搜索关键词"
+    @search="onRefresh"
+  />
+  <van-pull-refresh v-model="loading" @refresh="onRefresh">
+    <div class="list">
+      <van-list
+        v-model:loading="loading"
+        :finished="finished"
+        finished-text="没有更多了"
+        @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";
+const loading = ref(false);
+const router = useRoute();
+const req = ref({
+  pageNum: 1,
+  type: "1",
+  keyword: null,
+});
+const finished = ref(false);
+const proxy = getCurrentInstance().proxy;
+const listData = ref([]);
+
+const listConfig = ref([
+  {
+    label: "申购单号",
+    prop: "code",
+  },
+  {
+    label: "供应商",
+    prop: "supplyName",
+  },
+  {
+    label: "采购金额",
+    prop: "count",
+  },
+  {
+    label: "采购状态",
+    prop: "purchaseStatus",
+  },
+]);
+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("/main/purchasedAdd");
+};
+
+const toDtl = (row) => {
+  proxy.$router.push({
+    path: "purchasedAdd",
+    query: {
+      id: row.id,
+    },
+  });
+};
+
+const getList = (type) => {
+  loading.value = true;
+  proxy
+    .post("/purchase/page", req.value)
+    .then((res) => {
+      console.log(req.value);
+      res.data.rows.map((item) => {
+        item.purchaseStatus =
+          item.purchaseStatus === 0
+            ? "草稿"
+            : item.purchaseStatus === 10
+            ? "审批中"
+            : item.purchaseStatus === 20
+            ? "驳回"
+            : "通过";
+      });
+      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;
+    });
+};
+getList();
+</script>
+
+<style lang="scss" scoped>
+.list {
+  min-height: 70vh;
+}
+</style>