Browse Source

反馈模块制作

asd26269546 1 year ago
parent
commit
32cc1119af

+ 2 - 0
src/assets/css/index.scss

@@ -7,6 +7,8 @@ body {
     width: 100vw;
     min-height: 100vh;
     background-color: #f2f2f2;
+    max-width:500px;
+    margin: 0 auto;
 }
 
 ul,

BIN
src/assets/images/icon_ewm.png


BIN
src/assets/images/icon_gs.png


BIN
src/assets/images/icon_tele.png


+ 15 - 0
src/router/index.js

@@ -43,8 +43,23 @@ const routes = [{
 				name: '修改密码',
 				component: () => import('../views/home/changePassword.vue')
 			},
+			{
+				path: 'feedback',
+				name: '我的反馈',
+				component: () => import('../views/home/feedback.vue')
+			},
+			{
+				path: 'feedbackSubmit',
+				name: '我的反馈提交',
+				component: () => import('../views/home/feedbackSubmit.vue')
+			},
 			
 			{
+				path: 'feedbackDtl',
+				name: '我的反馈详情',
+				component: () => import('../views/home/feedbackDtl.vue')
+			},
+			{
 				path: 'message',
 				name: '消息通知',
 				component: () => import('../views/message/index.vue')

+ 173 - 0
src/views/home/feedback.vue

@@ -0,0 +1,173 @@
+<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" class="feedback">
+		<van-tabs v-model:active="active">
+            <van-tab title="全部">
+
+            </van-tab>
+            <van-tab title="待回复">
+                
+            </van-tab>
+            <van-tab title="已回复">
+
+            </van-tab>
+        </van-tabs>
+		<div class="list">
+			<van-list
+				v-model:loading="loading"
+				:finished="finished"
+				finished-text="没有更多了"
+				@load="onLoad"
+				style="margin-bottom:60px"
+			>
+                <ul>
+                    <li v-for="i in listData" :key="i.id" @click="toDtl(i)">
+                        <div class="title">
+                            反馈标题
+                        </div>
+                        <div class="time">
+                            2023-01-16 16:51
+                        </div>
+                        <div class="status">
+                            已回复
+                        </div>
+                    </li>
+                </ul>
+				<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 router = useRoute()
+const req = ref({
+	pageNum:1,
+	keyword:null
+})
+const finished = ref(false);
+const proxy = getCurrentInstance().proxy
+const listData = ref([])
+
+
+const listConfig = ref([
+	{
+		label: '仓库名称',
+		prop: 'name',
+	},
+	{
+		label: '仓库类型',
+		prop: 'typeName',
+	}
+])
+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/feedbackSubmit')
+}
+
+const toDtl = (row) => {
+	console.log(row)
+	proxy.$router.push({
+        path: 'feedbackDtl',
+		query: row
+      })
+}
+const warehouseType = ref([])
+
+const getDict = () => {
+    proxy.post('/dictTenantData/page',{
+        pageNum: 1,
+        pageSize: 999,
+        tenantId:getUserInfo().tenantId,
+        dictCode: "warehouse_type",
+    }).then(res => {
+		warehouseType.value = res.data.rows.map(item => {
+			return {
+				text: item.dictValue,
+				value: item.dictKey
+			}
+		})
+        getList()
+    })
+}
+
+const getList = (type) => {
+	loading.value = true
+	proxy.post('/warehouse/page',req.value).then(res => {	
+		res.data.rows.map(item => {
+			warehouseType.value.map(type => {
+				if(item.type == type.value) {
+					item.typeName = type.text
+				}
+			})
+		})
+		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
+	})
+}
+getDict()
+</script>
+
+<style lang="scss" scoped>
+.list {
+	min-height: 70vh;
+    ul{
+        li{
+            padding: 12px 20px;
+            background: #fff;
+            margin: 16px 12px 0;
+            border-radius: 8px;
+            line-height: 28px;
+            position: relative;
+            .status{
+                position: absolute;
+                right: 0;;
+                top: 0;
+                width: 60px;
+                height: 20px;
+                line-height: 20px;
+                text-align: center;
+                border-radius: 0px 8px 0px 8px;
+                font-size: 12px;
+                background: #A0BBFB;
+                color: #fff;
+            }
+        }
+    }
+}
+</style>

+ 83 - 0
src/views/home/feedbackDtl.vue

@@ -0,0 +1,83 @@
+<template>
+	<van-nav-bar
+		title="我的反馈"
+		left-text=""
+		left-arrow
+		@click-left="onClickLeft"
+	>
+		<template #right>
+			反馈
+		</template>
+	</van-nav-bar>
+    <div class="card">
+        <div class="content">
+            asdasd阿斯蒂芬斯蒂芬斯蒂芬时代大厦发 斯蒂芬说的都是反倒是方式地方
+        </div>
+        <div class="img-box">
+            
+        </div>
+        <div class="time">
+            2023-01-16 16:51
+        </div>
+    </div>
+	
+</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 router = useRoute()
+const req = ref({
+	pageNum:1,
+	keyword:null
+})
+const finished = ref(false);
+const proxy = getCurrentInstance().proxy
+const listData = ref([])
+
+
+const listConfig = ref([
+	{
+		label: '仓库名称',
+		prop: 'name',
+	},
+	{
+		label: '仓库类型',
+		prop: 'typeName',
+	}
+])
+const onRefresh = () => {
+	req.value.pageNum = 1
+	finished.value = false
+	getList('refresh')
+}
+const onLoad = () => {
+    getList()
+}
+
+const onClickLeft = () =>  proxy.$router.push('/main/feedback')
+
+const toDtl = (row) => {
+	console.log(row)
+	proxy.$router.push({
+        path: 'warehouseConfigAdd',
+		query: row
+      })
+}
+const warehouseType = ref([])
+
+
+
+</script>
+<style lang="scss" scoped>
+.card{
+    padding: 20px 12px;
+    margin: 12px 12px 0;
+    background: #fff;
+    border-radius: 8px;
+    font-size: 14px;
+    color: #333;
+}
+</style>

+ 282 - 0
src/views/home/feedbackSubmit.vue

@@ -0,0 +1,282 @@
+<template>
+	<div class="feedbackSubmit">
+		<div class="header">
+			<div class="title">
+				<div class="back" @click='backFn'>
+					<van-icon name="arrow-left" size="20" />
+				</div>
+				<div class="text">问题反馈</div>
+				<div class="more"></div>
+			</div>
+		</div>
+		<div class="contact card">
+			<div class="title">联系方式</div>
+			<ul>
+				<li>
+					<img src="../../assets/images/icon_gs.png" alt="" />
+					<span>福建数字云帆科技有限公司</span>
+				</li>
+				<li>
+					<img src="../../assets/images/icon_tele.png" alt="" />
+					<span>0591-87865886</span>
+				</li>
+				<li>
+					<img src="../../assets/images/icon_ewm.png" alt="" />
+					<span>数字云帆二维码</span>
+				</li>
+			</ul>
+			<div class="erweima">
+				<div>
+					<img src="../../assets/images/icon_ewm.png" alt="" />
+					<p>关注企业公众号</p>
+				</div>
+				<div>
+					<img src="../../assets/images/icon_ewm.png" alt="" />
+					<p>企业微信客服</p>
+				</div>
+			</div>
+		</div>
+		<div class="form-box">
+			<div class="title">问题反馈</div>
+			<testForm
+				v-model="formData.data"
+				:formOption="formOption"
+				:formConfig="formConfig"
+				:rules="rules"
+				@onSubmit="onSubmit"
+				ref="formDom"
+			></testForm>
+		</div>
+	</div>
+</template>
+<script setup>
+import { ref, reactive, getCurrentInstance, onMounted } from 'vue'
+import { showSuccessToast } from 'vant'
+import { useRoute } from 'vue-router'
+import { getUserInfo } from '@/utils/auth'
+import testForm from '@/components/testForm/index.vue'
+
+const proxy = getCurrentInstance().proxy
+const route = useRoute()
+const formDom = ref(null)
+const formData = reactive({
+	data: {
+		type: '',
+		keeperId: '',
+		name: '',
+		remark: '',
+	},
+})
+const backFn = () => {
+    history.go(-1)
+}
+const rules = {}
+const formOption = reactive({
+	readonly: false, //用于控制整个表单是否只读
+	disabled: false,
+	labelAlign: 'top',
+	scroll: true,
+	labelWidth: '62pk',
+})
+const formConfig = reactive([
+	{
+		type: 'input',
+		itemType: 'text',
+		label: '姓名',
+		prop: 'name',
+		clearable: true,
+	},
+	{
+		type: 'input',
+		itemType: 'text',
+		label: '公司名称',
+		prop: 'name',
+		clearable: true,
+	},
+	{
+		type: 'input',
+		itemType: 'text',
+		label: '联系方式',
+		prop: 'name',
+		clearable: true,
+	},
+	{
+		type: 'picker',
+		label: '模块类型',
+		prop: 'keeperId',
+		itemType: 'onePicker',
+		showPicker: false,
+		fieldNames: {
+			text: 'name',
+			value: 'id',
+		},
+		data: [
+			{
+				name: '模块1',
+				id: 1,
+			},
+			{
+				name: '模块2',
+				id: 2,
+			},
+		],
+	},
+	{
+		type: 'input',
+		itemType: '问题说明',
+		label: '备注',
+		prop: 'remark',
+		clearable: true,
+	},
+])
+const getDict = async () => {
+	await proxy
+		.post('/dictTenantData/page', {
+			pageNum: 1,
+			pageSize: 999,
+			tenantId: getUserInfo().tenantId,
+			dictCode: 'warehouse_type',
+		})
+		.then((res) => {
+			formConfig[0].data = res.data.rows
+		})
+	await proxy
+		.get('/tenantUser/list', {
+			pageNum: 1,
+			pageSize: 10000,
+			tenantId: getUserInfo().tenantId,
+		})
+		.then((res) => {
+			formConfig[1].data = res.rows
+		})
+}
+const onClickLeft = () => history.back()
+const onSubmit = () => {
+	proxy
+		.post('/warehouse/' + (!route.query.id ? 'add' : 'edit'), formData.data)
+		.then(() => {
+			showSuccessToast(!route.query.id ? '添加成功' : '编辑成功')
+			setTimeout(() => {
+				onClickLeft()
+			}, 500)
+		})
+}
+onMounted(async () => {
+	await getDict()
+	if (route.query.id) {
+		console.log(route.query.id)
+		proxy.post('/warehouse/detail', { id: route.query.id }).then((res) => {
+			formData.data = res.data
+		})
+	}
+})
+</script>
+<style lang="scss" scope>
+.header {
+	background: linear-gradient(0deg, #f1f1f1 0%, #46a6ff 46%, #0084ff 100%);
+	height: 160px;
+
+	.title {
+		display: flex;
+		justify-content: space-between;
+		height: 46px;
+		line-height: 46px;
+		padding: 0 12px;
+		color: #fff;
+		font-size: 16px;
+		font-weight: bold;
+		.back,
+		.more {
+			width: 40px;
+			height: 100%;
+		}
+	}
+}
+.form-box {
+	position: relative;
+	top: -80px;
+	margin: 0 12px;
+	border-radius: 8px;
+	background: #fff;
+	.title {
+		height: 52px;
+		line-height: 52px;
+		color: #333;
+		font-size: 16px;
+		font-weight: bold;
+		position: relative;
+		padding: 0 16px;
+	}
+	.title::before {
+		content: '';
+		display: inline-block;
+		width: 4px;
+		height: 12px;
+		background: #409eff;
+		position: absolute;
+		left: 0;
+		top: 20px;
+		background: #0084ff;
+		border-radius: 2px 2px 2px 2px;
+	}
+}
+.contact {
+	margin: 0 12px;
+	position: relative;
+	top: -100px;
+	ul {
+		line-height: 40px;
+		li {
+			display: flex;
+			padding: 0 16px;
+			img {
+				width: 24px;
+				height: 24px;
+				margin: 7px 12px 0 0;
+			}
+		}
+	}
+	.erweima {
+		display: flex;
+		justify-content: space-around;
+		padding: 20px 40px;
+		div {
+			img {
+				width: 110px;
+				height: 110px;
+			}
+			p {
+				text-align: center;
+				font-size: 16px;
+				color: #333;
+			}
+		}
+	}
+}
+.card {
+	background: linear-gradient(180deg, #d1e9fe 0%, #ffffff 100%);
+	border-radius: 8px 8px 8px 8px;
+	margin-top: 12px;
+	.title {
+		height: 52px;
+		line-height: 52px;
+		color: #333;
+		font-size: 16px;
+		font-weight: bold;
+		position: relative;
+		padding: 0 16px;
+	}
+	.title::before {
+		content: '';
+		display: inline-block;
+		width: 4px;
+		height: 12px;
+		background: #409eff;
+		position: absolute;
+		left: 0;
+		top: 20px;
+		background: #0084ff;
+		border-radius: 2px 2px 2px 2px;
+	}
+}
+</style>

+ 12 - 3
src/views/home/index.vue

@@ -22,7 +22,7 @@
 			</div>
 		</div>
 		<ul class="set-list">
-			<li @click="toChanagePassword">
+			<li @click="toRouter('changePassword')">
 				<div class="icon-box">
 					<i class="iconfont icon-icon_pz"></i>
 				</div>
@@ -31,6 +31,15 @@
 					<van-icon name="arrow" size="16" />
 				</div>
 			</li>
+			<li @click="toRouter('feedback')">
+				<div class="icon-box">
+					<i class="iconfont icon-icomx_kefu"></i>
+				</div>
+				<div class="text">我的反馈</div>
+				<div class="more">
+					<van-icon name="arrow" size="16" />
+				</div>
+			</li>
 		</ul>
 		<van-button class="logout" type="primary" @click="logout" block
 			>退出登录</van-button
@@ -49,8 +58,8 @@ console.log(userInfo)
 const toMessageList = () => {
 	proxy.$router.push('/main/messageList')
 }
-const toChanagePassword = () => {
-    proxy.$router.push('/main/changePassword')
+const toRouter = (url) => {
+    proxy.$router.push('/main/' + url)
 }
 const logout = () => {
 	showConfirmDialog({

+ 134 - 259
src/views/product-material/product-library/add.vue

@@ -7,137 +7,134 @@
 			@click-left="onClickLeft"
 		>
 		</van-nav-bar>
-		<van-form
-			@submit="onSubmit"
-			label-align="top"
-			style="margin-top: 20px; overflow-y: auto"
-		>
-			<van-cell-group inset>
-				<van-field
-					v-model="formData.productClassifyName"
-					is-link
-					readonly
-					label="产品分类"
-					placeholder="请选择产品分类"
-					@click="show = true"
-					:rules="[{ required: true, message: '产品分类不能为空' }]"
-					required
-				/>
-				<van-popup v-model:show="show" round position="bottom">
-					<van-cascader
-						title="请选择产品分类"
-						:options="classification"
-						:field-names="fieldNames"
-						@close="show = false"
-						@change="onChange"
-						@finish="onFinish"
-					/>
-				</van-popup>
-				<van-field
-					v-model="formData.typeName"
-					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="typeList"
-						@cancel="typeModal = false"
-						@confirm="onConfirmType"
-					/>
-				</van-popup>
-				<van-field
-					v-model="formData.name"
-					name="产品名称"
-					label="产品名称"
-					placeholder="请填写产品名称"
-					:rules="[{ required: true, message: '产品名称不能为空' }]"
-					required
-				/>
-				<van-field
-					v-model="formData.spec"
-					name="规格型号"
-					label="规格型号"
-					placeholder="请填写规格型号"
-					:rules="[{ required: true, message: '规格型号不能为空' }]"
-					required
-				/>
-				<van-field
-					v-model="formData.unitName"
-					is-link
-					readonly
-					label="单位"
-					placeholder="选择单位"
-					@click="unitModal = true"
-					:rules="[{ required: true, message: '单位不能为空' }]"
-					required
-				/>
-				<van-popup v-model:show="unitModal" round position="bottom">
-					<van-picker
-						:columns="unitList"
-						@cancel="unitModal = false"
-						@confirm="onConfirmUnit"
-					/>
-				</van-popup>
-				<van-field name="uploader" label="文件上传">
-					<template #input>
-						<van-uploader
-							v-model="fileList"
-							:after-read="afterRead"
-							multiple
-							:max-count="9"
-							:max-size="5 * 1024 * 1024"
-							@oversize="onOversize"
-						/>
-					</template>
-				</van-field>
-				<van-field
-					v-model="formData.remark"
-					rows="3"
-					type="textarea"
-					name="备注"
-					label="备注"
-					placeholder="请填写备注"
-				/>
-			</van-cell-group>
-			<div style="margin: 16px">
-				<van-button round block type="primary" native-type="submit">
-					提交
-				</van-button>
-			</div>
-		</van-form>
+		
+    <testForm
+      v-model="formData.data"
+      :formOption="formOption"
+      :formConfig="formConfig"
+      :rules="rules"
+      @onSubmit="onSubmit"
+      ref="formDom"
+    ></testForm>
 	</div>
 </template>
 
 <script setup>
-import { ref, getCurrentInstance, onMounted } from "vue";
+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";
 const proxy = getCurrentInstance().proxy;
 const route = useRoute();
 const show = ref(false);
 const typeModal = ref(false);
 const unitModal = ref(false);
 const classification = ref([]);
-const fieldNames = {
-  text: "label",
-  value: "id",
-};
-const typeList = ref([
+const formData = reactive({
+  data: {
+  },
+});
+const formDom = ref(null);
+const formOption = reactive({
+  readonly: false, //用于控制整个表单是否只读
+  disabled: false,
+  labelAlign: "top",
+  scroll: true,
+  labelWidth: "62pk",
+  // hiddenSubmitBtn: true,
+});
+const formConfig = reactive([
+  {
+    type: "cascader",
+    label: "产品分类",
+    prop: "productClassifyId",
+    itemType: "common",
+    showPicker: false,
+    // data: classification.value,
+    data: [],
+    fieldNames: {
+      text: "label",
+      value: "id",
+      children: "children",
+    },
+    // onChangeFn: (option) => {
+    //   // console.log("aa");
+    // },
+    // finishFn: (current, option) => {
+    //   current.showPicker = false;
+    // },
+  },
+  {
+    type: "picker",
+    label: "产品类型",
+    prop: "type",
+    itemType: "onePicker",
+    showPicker: false,
+    fieldNames: {
+      text: "label",
+      value: "id",
+    },
+    data: [
+      {
+        label: "成品",
+        id: "10",
+      },
+      {
+        label: "半成品",
+        id: "2",
+      },
+    ],
+  },
+  {
+    type: "input",
+    itemType: "text",
+    label: "产品名称",
+    prop: "name",
+    clearable: true,
+  },
+  {
+    type: "input",
+    itemType: "text",
+    label: "规格型号",
+    prop: "spec",
+    clearable: true,
+  },
+  {
+    type: "picker",
+    label: "单位",
+    prop: "unit",
+    itemType: "onePicker",
+    showPicker: false,
+    fieldNames: {
+      text: "dictValue",
+      value: "dictKey",
+    },
+    data: []
+  },
   {
-    text: "成品",
-    value: "1",
+    type: "upload",
+    label: "文件上传",
+    prop: "fileList",
   },
   {
-    text: "半成品",
-    value: "2",
+    type: "input",
+    itemType: "textarea",
+    label: "富文本",
+    prop: "remark",
   },
 ]);
+const rules = {
+  name: [{ required: true, message: "请填写姓名" }],
+  password: [{ required: true, message: "请填写密码" }],
+  reamlke: [{ required: true, message: "请填写备注" }],
+  checkbox: [{ required: true, message: "请选择" }],
+  radio: [{ required: true, message: "请选择" }],
+  select: [{ required: true, message: "请选择" }],
+  date: [{ required: true, message: "请选择时间" }],
+  common: [{ required: true, message: "请选择级联" }],
+  // city: [{ required: true, message: "请选择城市" }],
+};
 const unitList = ref([]);
 
 const getDict = () => {
@@ -149,127 +146,20 @@ const getDict = () => {
       dictCode: "unit",
     })
     .then((res) => {
-      unitList.value = res.data.rows.map((item, index) => {
-        return {
-          text: item.dictValue,
-          value: item.dictKey,
-        }
-      })
+      formConfig[4].data = res.data.rows
+      formDom.value.formDataInit(true);
     })
 }
 getDict()
-const formData = ref({
-  id: null,
-  definition: "1",
-  productClassifyId: null,
-  productClassifyName: null,
-  code: null,
-  customCode: null,
-  type: null,
-  typeName: null,
-  name: null,
-  spec: null,
-  unit: null,
-  remark: null,
-  fileList: [],
-});
-const onConfirmType = ({ selectedOptions }) => {
-  formData.value.type = selectedOptions[0].value;
-  formData.value.typeName = selectedOptions[0].text;
-  typeModal.value = false;
-};
-const onConfirmUnit = ({ selectedOptions }) => {
-  formData.value.unit = selectedOptions[0].value;
-   formData.value.unitName = selectedOptions[0].text;
-  unitModal.value = false;
-};
-const onChange = ({ selectedOptions }) => {
-  if (selectedOptions && selectedOptions.length > 0) {
-    formData.value.productClassifyId = selectedOptions[selectedOptions.length - 1].id;
-    formData.value.productClassifyName = selectedOptions[selectedOptions.length - 1].label;
-  }
-};
-const onFinish = ({ selectedOptions }) => {
-  show.value = false;
-  if (selectedOptions && selectedOptions.length > 0) {
-    formData.value.productClassifyId = selectedOptions[selectedOptions.length - 1].id;
-    formData.value.productClassifyName = selectedOptions[selectedOptions.length - 1].label;
-  }
-};
 const fileList = ref([]);
-const afterRead = (file) => {
-  if (file && file.length > 0) {
-    for (let i = 0; i < file.length; i++) {
-      file[i].status = "uploading";
-      file[i].message = "上传中...";
-      proxy.post("/fileInfo/getSing", { fileName: file[i].file.name }).then(
-        (res) => {
-          let forms = new FormData();
-          forms.append("file", file[i].file);
-          proxy.post("https://winfaster.obs.cn-south-1.myhuaweicloud.com", { ...res.data.uploadBody, file: forms.get("file") }).then(
-            () => {
-              file[i].id = res.data.id;
-              file[i].url = res.data.fileUrl;
-              file[i].fileName = res.data.fileName;
-              delete file[i].status;
-              delete file[i].message;
-            },
-            () => {
-              file[i].status = "failed";
-              file[i].message = "上传失败";
-            }
-          );
-        },
-        () => {
-          file[i].status = "failed";
-          file[i].message = "上传失败";
-        }
-      );
-    }
-  } else {
-    file.status = "uploading";
-    file.message = "上传中...";
-    proxy.post("/fileInfo/getSing", { fileName: file.file.name }).then(
-      (res) => {
-        let forms = new FormData();
-        forms.append("file", file.file);
-        proxy.post("https://winfaster.obs.cn-south-1.myhuaweicloud.com", { ...res.data.uploadBody, file: forms.get("file") }).then(
-          () => {
-            file.id = res.data.id;
-            file.url = res.data.fileUrl;
-            file.fileName = res.data.fileName;
-            delete file.status;
-            delete file.message;
-          },
-          () => {
-            file.status = "failed";
-            file.message = "上传失败";
-          }
-        );
-      },
-      () => {
-        file.status = "failed";
-        file.message = "上传失败";
-      }
-    );
-  }
-};
 const onOversize = () => {
   showToast("文件大小不能超过 5MB");
 };
 const onClickLeft = () => history.back();
 const onSubmit = () => {
-  if (fileList.value && fileList.value.length > 0) {
-    formData.value.fileList = fileList.value.map((item) => {
-      return {
-        id: item.id,
-        fileName: item.fileName,
-      };
-    });
-  } else {
-    formData.value.fileList = [];
-  }
-  proxy.post("/productInfo/" + route.query.type, formData.value).then(() => {
+  console.log(formData)
+  
+  proxy.post("/productInfo/" + route.query.type, formData.data).then(() => {
     showSuccessToast("添加成功");
     setTimeout(() => {
       history.back();
@@ -290,44 +180,29 @@ const treeToList = (arr) => {
 };
 onMounted(() => {
   proxy.post("/productClassify/tree", { parentId: "", name: "", definition: "1" }).then((res) => {
-    classification.value = res.data;
+    formConfig[0].data = res.data;
     let classList = treeToList(res.data);
     if (route.query.id) {
       proxy.post("/productInfo/detail", { id: route.query.id }).then((resDetail) => {
-        formData.value.id = route.query.id;
-        formData.value.productClassifyId = resDetail.data.productClassifyId;
-        let data = classList.filter((item) => item.id === resDetail.data.productClassifyId);
-        if (data && data.length > 0) {
-          formData.value.productClassifyName = data[0].label;
-        }
-        formData.value.code = resDetail.data.code;
-        formData.value.customCode = resDetail.data.customCode;
-        formData.value.type = resDetail.data.type;
-        let typeNameList = typeList.value.filter((item) => item.value == resDetail.data.type);
-        if (typeNameList && typeNameList.length > 0) {
-          formData.value.typeName = typeNameList[0].text;
-        }
-        formData.value.name = resDetail.data.name;
-        formData.value.spec = resDetail.data.spec;
-        formData.value.unit = resDetail.data.unit;
-        formData.value.remark = resDetail.data.remark;
-        console.log(unitList.value.filter((item) => item.value == resDetail.data.unit))
-        formData.value.unitName = unitList.value.filter((item) => item.value == resDetail.data.unit)[0].text;
-      });
-      proxy.post("/fileInfo/getList", { businessIdList: [route.query.id] }).then((res) => {
-        if (res.data[route.query.id] && res.data[route.query.id].length > 0) {
-          formData.value.fileList = res.data[route.query.id];
-          fileList.value = res.data[route.query.id].map((item) => {
-            return {
-              ...item,
-              url: item.fileUrl,
-            };
-          });
-        } else {
-          formData.value.fileList = [];
-          fileList.value = [];
-        }
+        formData.data = resDetail.data
+        
       });
+      // proxy.post("/fileInfo/getList", { businessIdList: [route.query.id] }).then((res) => {
+      //   if (res.data[route.query.id] && res.data[route.query.id].length > 0) {
+      //     formData.value.fileList = res.data[route.query.id];
+      //     fileList.value = res.data[route.query.id].map((item) => {
+      //       return {
+      //         ...item,
+      //         url: item.fileUrl,
+      //       };
+      //     });
+      //   } else {
+      //     formData.value.fileList = [];
+      //     fileList.value = [];
+      //   }
+      // });
+    }else {
+      
     }
   });
 });

+ 334 - 0
src/views/product-material/product-library/add2.vue

@@ -0,0 +1,334 @@
+<template>
+	<div class="form">
+		<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; overflow-y: auto"
+		>
+			<van-cell-group inset>
+				<van-field
+					v-model="formData.productClassifyName"
+					is-link
+					readonly
+					label="产品分类"
+					placeholder="请选择产品分类"
+					@click="show = true"
+					:rules="[{ required: true, message: '产品分类不能为空' }]"
+					required
+				/>
+				<van-popup v-model:show="show" round position="bottom">
+					<van-cascader
+						title="请选择产品分类"
+						:options="classification"
+						:field-names="fieldNames"
+						@close="show = false"
+						@change="onChange"
+						@finish="onFinish"
+					/>
+				</van-popup>
+				<van-field
+					v-model="formData.typeName"
+					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="typeList"
+						@cancel="typeModal = false"
+						@confirm="onConfirmType"
+					/>
+				</van-popup>
+				<van-field
+					v-model="formData.name"
+					name="产品名称"
+					label="产品名称"
+					placeholder="请填写产品名称"
+					:rules="[{ required: true, message: '产品名称不能为空' }]"
+					required
+				/>
+				<van-field
+					v-model="formData.spec"
+					name="规格型号"
+					label="规格型号"
+					placeholder="请填写规格型号"
+					:rules="[{ required: true, message: '规格型号不能为空' }]"
+					required
+				/>
+				<van-field
+					v-model="formData.unitName"
+					is-link
+					readonly
+					label="单位"
+					placeholder="选择单位"
+					@click="unitModal = true"
+					:rules="[{ required: true, message: '单位不能为空' }]"
+					required
+				/>
+				<van-popup v-model:show="unitModal" round position="bottom">
+					<van-picker
+						:columns="unitList"
+						@cancel="unitModal = false"
+						@confirm="onConfirmUnit"
+					/>
+				</van-popup>
+				<van-field name="uploader" label="文件上传">
+					<template #input>
+						<van-uploader
+							v-model="fileList"
+							:after-read="afterRead"
+							multiple
+							:max-count="9"
+							:max-size="5 * 1024 * 1024"
+							@oversize="onOversize"
+						/>
+					</template>
+				</van-field>
+				<van-field
+					v-model="formData.remark"
+					rows="3"
+					type="textarea"
+					name="备注"
+					label="备注"
+					placeholder="请填写备注"
+				/>
+			</van-cell-group>
+			<div style="margin: 16px">
+				<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, showToast } from "vant";
+import { useRoute } from "vue-router";
+import { getUserInfo } from '@/utils/auth';
+const proxy = getCurrentInstance().proxy;
+const route = useRoute();
+const show = ref(false);
+const typeModal = ref(false);
+const unitModal = ref(false);
+const classification = ref([]);
+const fieldNames = {
+  text: "label",
+  value: "id",
+};
+const typeList = ref([
+  {
+    text: "成品",
+    value: "1",
+  },
+  {
+    text: "半成品",
+    value: "2",
+  },
+]);
+const unitList = ref([]);
+
+const getDict = () => {
+  proxy
+    .post("/dictTenantData/page", {
+      pageNum: 1,
+      pageSize: 999,
+      tenantId: getUserInfo().tenantId,
+      dictCode: "unit",
+    })
+    .then((res) => {
+      unitList.value = res.data.rows.map((item, index) => {
+        return {
+          text: item.dictValue,
+          value: item.dictKey,
+        }
+      })
+    })
+}
+getDict()
+const formData = ref({
+  id: null,
+  definition: "1",
+  productClassifyId: null,
+  productClassifyName: null,
+  code: null,
+  customCode: null,
+  type: null,
+  typeName: null,
+  name: null,
+  spec: null,
+  unit: null,
+  remark: null,
+  fileList: [],
+});
+const onConfirmType = ({ selectedOptions }) => {
+  formData.value.type = selectedOptions[0].value;
+  formData.value.typeName = selectedOptions[0].text;
+  typeModal.value = false;
+};
+const onConfirmUnit = ({ selectedOptions }) => {
+  formData.value.unit = selectedOptions[0].value;
+   formData.value.unitName = selectedOptions[0].text;
+  unitModal.value = false;
+};
+const onChange = ({ selectedOptions }) => {
+  if (selectedOptions && selectedOptions.length > 0) {
+    formData.value.productClassifyId = selectedOptions[selectedOptions.length - 1].id;
+    formData.value.productClassifyName = selectedOptions[selectedOptions.length - 1].label;
+  }
+};
+const onFinish = ({ selectedOptions }) => {
+  show.value = false;
+  if (selectedOptions && selectedOptions.length > 0) {
+    formData.value.productClassifyId = selectedOptions[selectedOptions.length - 1].id;
+    formData.value.productClassifyName = selectedOptions[selectedOptions.length - 1].label;
+  }
+};
+const fileList = ref([]);
+const afterRead = (file) => {
+  if (file && file.length > 0) {
+    for (let i = 0; i < file.length; i++) {
+      file[i].status = "uploading";
+      file[i].message = "上传中...";
+      proxy.post("/fileInfo/getSing", { fileName: file[i].file.name }).then(
+        (res) => {
+          let forms = new FormData();
+          forms.append("file", file[i].file);
+          proxy.post("https://winfaster.obs.cn-south-1.myhuaweicloud.com", { ...res.data.uploadBody, file: forms.get("file") }).then(
+            () => {
+              file[i].id = res.data.id;
+              file[i].url = res.data.fileUrl;
+              file[i].fileName = res.data.fileName;
+              delete file[i].status;
+              delete file[i].message;
+            },
+            () => {
+              file[i].status = "failed";
+              file[i].message = "上传失败";
+            }
+          );
+        },
+        () => {
+          file[i].status = "failed";
+          file[i].message = "上传失败";
+        }
+      );
+    }
+  } else {
+    file.status = "uploading";
+    file.message = "上传中...";
+    proxy.post("/fileInfo/getSing", { fileName: file.file.name }).then(
+      (res) => {
+        let forms = new FormData();
+        forms.append("file", file.file);
+        proxy.post("https://winfaster.obs.cn-south-1.myhuaweicloud.com", { ...res.data.uploadBody, file: forms.get("file") }).then(
+          () => {
+            file.id = res.data.id;
+            file.url = res.data.fileUrl;
+            file.fileName = res.data.fileName;
+            delete file.status;
+            delete file.message;
+          },
+          () => {
+            file.status = "failed";
+            file.message = "上传失败";
+          }
+        );
+      },
+      () => {
+        file.status = "failed";
+        file.message = "上传失败";
+      }
+    );
+  }
+};
+const onOversize = () => {
+  showToast("文件大小不能超过 5MB");
+};
+const onClickLeft = () => history.back();
+const onSubmit = () => {
+  if (fileList.value && fileList.value.length > 0) {
+    formData.value.fileList = fileList.value.map((item) => {
+      return {
+        id: item.id,
+        fileName: item.fileName,
+      };
+    });
+  } else {
+    formData.value.fileList = [];
+  }
+  proxy.post("/productInfo/" + route.query.type, formData.value).then(() => {
+    showSuccessToast("添加成功");
+    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;
+};
+onMounted(() => {
+  proxy.post("/productClassify/tree", { parentId: "", name: "", definition: "1" }).then((res) => {
+    classification.value = res.data;
+    let classList = treeToList(res.data);
+    if (route.query.id) {
+      proxy.post("/productInfo/detail", { id: route.query.id }).then((resDetail) => {
+        formData.value.id = route.query.id;
+        formData.value.productClassifyId = resDetail.data.productClassifyId;
+        let data = classList.filter((item) => item.id === resDetail.data.productClassifyId);
+        if (data && data.length > 0) {
+          formData.value.productClassifyName = data[0].label;
+        }
+        formData.value.code = resDetail.data.code;
+        formData.value.customCode = resDetail.data.customCode;
+        formData.value.type = resDetail.data.type;
+        let typeNameList = typeList.value.filter((item) => item.value == resDetail.data.type);
+        if (typeNameList && typeNameList.length > 0) {
+          formData.value.typeName = typeNameList[0].text;
+        }
+        formData.value.name = resDetail.data.name;
+        formData.value.spec = resDetail.data.spec;
+        formData.value.unit = resDetail.data.unit;
+        formData.value.remark = resDetail.data.remark;
+        console.log(unitList.value.filter((item) => item.value == resDetail.data.unit))
+        formData.value.unitName = unitList.value.filter((item) => item.value == resDetail.data.unit)[0].text;
+      });
+      proxy.post("/fileInfo/getList", { businessIdList: [route.query.id] }).then((res) => {
+        if (res.data[route.query.id] && res.data[route.query.id].length > 0) {
+          formData.value.fileList = res.data[route.query.id];
+          fileList.value = res.data[route.query.id].map((item) => {
+            return {
+              ...item,
+              url: item.fileUrl,
+            };
+          });
+        } else {
+          formData.value.fileList = [];
+          fileList.value = [];
+        }
+      });
+    }
+  });
+});
+</script>

+ 2 - 2
src/views/warehouse/warehouseConfig/index.vue

@@ -49,7 +49,7 @@ const listConfig = ref([
 	},
 	{
 		label: '仓库类型',
-		prop: 'type',
+		prop: 'typeName',
 	}
 ])
 const onRefresh = () => {
@@ -99,7 +99,7 @@ const getList = (type) => {
 		res.data.rows.map(item => {
 			warehouseType.value.map(type => {
 				if(item.type == type.value) {
-					item.type = type.text
+					item.typeName = type.text
 				}
 			})
 		})