form.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395
  1. <script lang="ts" setup>
  2. import type { ProductEntity } from '@vben/types';
  3. import { computed, ref } from 'vue';
  4. import { useVbenModal } from '@vben/common-ui';
  5. import { ElMessage } from 'element-plus';
  6. import { useVbenForm, z } from '#/adapter/form';
  7. import {
  8. addProductApi,
  9. editProductApi,
  10. getProductDetailApi,
  11. } from '#/api/product';
  12. import { getScqyListApi } from '#/api/scqy';
  13. import { getCustomerListApi } from '#/api/user';
  14. // 定义 props
  15. const props = defineProps<{
  16. defaultMerchantId?: string | string[];
  17. }>();
  18. const emit = defineEmits(['finish']);
  19. const data = ref();
  20. const formType = ref<'create' | 'detail' | 'edit'>('create');
  21. const channelOptions = ref<{ label: string; value: string }[]>([]);
  22. const scqyOptions = ref<{ label: string; value: string }[]>([]);
  23. // 获取渠道商列表
  24. const fetchChannelOptions = async () => {
  25. try {
  26. // 确保清空之前的选项
  27. channelOptions.value = [];
  28. const response = await getCustomerListApi({
  29. 'usersnature.value': '经销商',
  30. pageindex: 1,
  31. rows: 100,
  32. });
  33. // 从response.Data中获取数据
  34. if (response && response.Data && Array.isArray(response.Data)) {
  35. channelOptions.value = response.Data.map((item: any) => ({
  36. label: item.usersname || '未命名渠道商',
  37. value: item.usersid || '',
  38. })).filter((item: any) => item.value);
  39. }
  40. } catch (error) {
  41. console.error('获取渠道商列表失败', error);
  42. }
  43. };
  44. // 获取生产企业列表
  45. const fetchScqyOptions = async () => {
  46. try {
  47. // 确保清空之前的选项
  48. scqyOptions.value = [];
  49. const response = await getScqyListApi({
  50. pageindex: 1,
  51. rows: 100,
  52. });
  53. // 从response.Data中获取数据
  54. if (response && response.Data && Array.isArray(response.Data)) {
  55. scqyOptions.value = response.Data.map((item: any) => ({
  56. label: item.scqyinfomc || '未命名生产企业',
  57. value: item.scqyinfoid || '',
  58. })).filter((item: any) => item.value);
  59. }
  60. } catch (error) {
  61. console.error('获取生产企业列表失败', error);
  62. }
  63. };
  64. const titleMap = {
  65. create: '新增产品',
  66. detail: '产品详情',
  67. edit: '编辑产品',
  68. } as const;
  69. const getTitle = computed(() => titleMap[formType.value]);
  70. // 判断是否有默认的渠道商ID
  71. const hasDefaultMerchantId = computed(() => {
  72. return props.defaultMerchantId &&
  73. (Array.isArray(props.defaultMerchantId) ? props.defaultMerchantId.length > 0 : props.defaultMerchantId);
  74. });
  75. // 获取默认渠道商ID的数组形式
  76. const defaultMerchantIdArray = computed(() => {
  77. if (!props.defaultMerchantId) return [];
  78. return Array.isArray(props.defaultMerchantId) ? props.defaultMerchantId : [props.defaultMerchantId];
  79. });
  80. const [BaseForm, baseFormApi] = useVbenForm({
  81. showDefaultActions: false,
  82. // 所有表单项共用,可单独在表单内覆盖
  83. commonConfig: {
  84. labelWidth: 140,
  85. // 所有表单项
  86. componentProps: {
  87. class: 'w-full',
  88. },
  89. },
  90. wrapperClass: 'grid-cols-1 lg:grid-cols-2',
  91. schema: [
  92. // { title: '产品名称', field: 'productsname' },
  93. // { title: '产品类别', field: 'productscategory' },
  94. // { title: '产品原价', field: 'productsprice' },
  95. // { title: '产品型号', field: 'productsmodel' },
  96. // { title: '产品sn号', field: 'productssn' },
  97. // { title: '品目', field: 'productspm' },
  98. // { title: '一级分类', field: 'productsfl1' },
  99. // { title: '二级分类', field: 'productsfl2' },
  100. // { title: '分档名称', field: 'productsfdmc' },
  101. // { title: '分档编号', field: 'productsfdbh' },
  102. // { title: '中央补贴金额', field: 'productszybt' },
  103. // { title: '特殊县中央补贴金额', field: 'productstsxzybt' },
  104. // { title: '机具类型', field: 'productsjjlx' },
  105. {
  106. component: 'Input',
  107. fieldName: 'productsjjlx',
  108. label: '机具类型',
  109. componentProps: {
  110. placeholder: '请输入机具类型',
  111. allowClear: true,
  112. },
  113. rules: z.string().min(1, { message: '请输入机具类型' }),
  114. },
  115. {
  116. component: 'Input',
  117. fieldName: 'productsname',
  118. label: '产品名称',
  119. componentProps: {
  120. placeholder: '请输入产品名称',
  121. allowClear: true,
  122. },
  123. rules: z.string().min(1, { message: '请输入产品名称' }),
  124. },
  125. {
  126. component: 'Input',
  127. fieldName: 'productscategory',
  128. label: '产品类别',
  129. componentProps: {
  130. placeholder: '请输入产品类别',
  131. allowClear: true,
  132. },
  133. rules: z.string().min(1, { message: '请输入产品类别' }),
  134. },
  135. {
  136. component: 'Input',
  137. fieldName: 'productsmodel',
  138. label: '产品型号',
  139. componentProps: {
  140. placeholder: '请输入产品型号',
  141. allowClear: true,
  142. },
  143. rules: z.string().min(1, { message: '请输入产品型号' }),
  144. },
  145. // {
  146. // component: 'Input',
  147. // fieldName: 'productssn',
  148. // label: '产品SN号',
  149. // componentProps: {
  150. // placeholder: '请输入产品SN号',
  151. // allowClear: true,
  152. // },
  153. // rules: z.string().min(1, { message: '请输入产品SN号' }),
  154. // },
  155. {
  156. component: 'Input',
  157. fieldName: 'productspm',
  158. label: '品目',
  159. componentProps: {
  160. placeholder: '请输入品目',
  161. allowClear: true,
  162. },
  163. rules: z.string().min(1, { message: '请输入品目' }),
  164. },
  165. {
  166. component: 'Select',
  167. fieldName: 'productsmerchantid',
  168. label: '关联渠道商',
  169. componentProps: {
  170. placeholder: '请选择关联渠道商',
  171. options: channelOptions,
  172. multiple: true,
  173. collapseTags: true,
  174. collapseTagsTooltip: true,
  175. clearable: true,
  176. filterable: true,
  177. noDataText: '暂无渠道商数据',
  178. loading: false,
  179. style: { width: '100%' },
  180. },
  181. rules: z.array(z.string()).min(1, { message: '请选择关联渠道商' }),
  182. // 使用dependencies控制字段显示
  183. dependencies: {
  184. triggerFields: ['productsname'], // 依赖产品名称字段来触发重新计算
  185. show: () => !hasDefaultMerchantId.value, // 当没有默认值时才显示该字段
  186. },
  187. },
  188. {
  189. component: 'Select',
  190. fieldName: 'productsscqyid',
  191. label: '关联生产企业',
  192. componentProps: {
  193. placeholder: '请选择关联生产企业',
  194. options: scqyOptions,
  195. clearable: true,
  196. filterable: true,
  197. noDataText: '暂无生产企业数据',
  198. loading: false,
  199. style: { width: '100%' },
  200. },
  201. rules: z.string().min(1, { message: '请选择关联生产企业' }),
  202. },
  203. {
  204. component: 'Input',
  205. fieldName: 'productsfl1',
  206. label: '一级分类',
  207. componentProps: {
  208. placeholder: '请输入一级分类',
  209. allowClear: true,
  210. },
  211. rules: z.string().min(1, { message: '请输入一级分类' }),
  212. },
  213. {
  214. component: 'Input',
  215. fieldName: 'productsfl2',
  216. label: '二级分类',
  217. componentProps: {
  218. placeholder: '请输入二级分类',
  219. allowClear: true,
  220. },
  221. rules: z.string().min(1, { message: '请输入二级分类' }),
  222. },
  223. {
  224. component: 'Input',
  225. fieldName: 'productsfdmc',
  226. label: '分档名称',
  227. componentProps: {
  228. placeholder: '请输入分档名称',
  229. allowClear: true,
  230. },
  231. rules: z.string().min(1, { message: '请输入分档名称' }),
  232. },
  233. {
  234. component: 'Input',
  235. fieldName: 'productsfdbh',
  236. label: '分档编号',
  237. componentProps: {
  238. placeholder: '请输入分档编号',
  239. allowClear: true,
  240. },
  241. rules: z.string().min(1, { message: '请输入分档编号' }),
  242. },
  243. {
  244. component: 'InputNumber',
  245. fieldName: 'productsprice',
  246. label: '产品原价',
  247. componentProps: {
  248. placeholder: '请输入产品原价',
  249. min: 0,
  250. precision: 2,
  251. },
  252. rules: z.number().min(0, { message: '请输入正确的产品原价' }),
  253. },
  254. {
  255. component: 'InputNumber',
  256. fieldName: 'productszybt',
  257. label: '中央补贴',
  258. componentProps: {
  259. placeholder: '请输入中央补贴金额',
  260. min: 0,
  261. precision: 2,
  262. },
  263. rules: z.number().min(0, { message: '请输入正确的中央补贴金额' }),
  264. },
  265. {
  266. component: 'InputNumber',
  267. fieldName: 'productstsxzybt',
  268. label: '特殊县中央补贴',
  269. componentProps: {
  270. placeholder: '请输入特殊县中央补贴金额',
  271. min: 0,
  272. precision: 2,
  273. },
  274. rules: z.number().min(0, { message: '请输入正确的特殊县中央补贴金额' }),
  275. },
  276. ],
  277. });
  278. const [Modal, modalApi] = useVbenModal({
  279. class: 'w-7/12',
  280. onCancel() {
  281. modalApi.close();
  282. },
  283. async onConfirm() {
  284. // 校验输入的数据
  285. const validate = await baseFormApi.validate();
  286. if (!validate.valid) {
  287. return;
  288. }
  289. try {
  290. // 处理多选值的转换
  291. const formValues = { ...validate.values };
  292. if (Array.isArray(formValues.productsmerchantid)) {
  293. formValues.productsmerchantid = formValues.productsmerchantid.join(',');
  294. }
  295. // 调用新增或编辑接口
  296. const apiMap = {
  297. create: () => addProductApi(formValues as ProductEntity),
  298. edit: () =>
  299. editProductApi({
  300. ...formValues,
  301. 'productsid.value': data.value.row.productsid,
  302. } as any),
  303. };
  304. if (formType.value === 'detail') {
  305. modalApi.close();
  306. return;
  307. }
  308. await apiMap[formType.value]();
  309. ElMessage.success('操作成功');
  310. emit('finish');
  311. modalApi.close();
  312. } catch {}
  313. },
  314. async onOpenChange(isOpen) {
  315. if (isOpen) {
  316. data.value = modalApi.getData();
  317. formType.value = data.value.formType;
  318. baseFormApi.setState({
  319. commonConfig: { disabled: formType.value === 'detail' },
  320. });
  321. // 获取渠道商列表和生产企业列表
  322. await Promise.all([fetchChannelOptions(), fetchScqyOptions()]);
  323. // 如果有默认的渠道商ID,设置默认值
  324. if (hasDefaultMerchantId.value && data.value.formType === 'create') {
  325. // 设置默认值
  326. baseFormApi.setValues({
  327. productsmerchantid: '', // 设置为空的目的,是在接下来的经销商关联时,再去选择关联,而不是直接就进行关联
  328. });
  329. }
  330. if (data.value.formType === 'create') {
  331. return;
  332. }
  333. try {
  334. modalApi.setState({ loading: true });
  335. const detailData = await getProductDetailApi({
  336. productsid: data.value.row.productsid,
  337. });
  338. // 处理多选值的转换
  339. if (detailData.productsmerchantid) {
  340. detailData.productsmerchantid =
  341. detailData.productsmerchantid.split(',');
  342. }
  343. baseFormApi.setValues(detailData);
  344. } catch (error) {
  345. console.error('获取产品详情失败', error);
  346. }
  347. modalApi.setState({ loading: false });
  348. }
  349. },
  350. });
  351. // 暴露modalApi供外部调用
  352. defineExpose({
  353. modalApi,
  354. });
  355. </script>
  356. <template>
  357. <Modal :title="getTitle">
  358. <BaseForm />
  359. </Modal>
  360. </template>