针对标签中设置 disabled="true",$("#id").serialize()获取不到value的解决方法

本文探讨了在JavaScript中使用$(#form).serialize()方法时遇到的问题,当<select>元素被设置为disabled状态时,其值不会被包含在序列化的结果中。文中提供了两种解决方案:一种是在序列化前移除disabled属性;另一种是将disabled替换为readonly。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  今天给<select>增加disabled="true", 发现$("#form").serialize()的结果不包含select标签的值,解决办法有如下两种:

  1. $("#form").serialize()之前去掉select的disabled属性,$("#role").removeAttr("disabled");

  2. 修改disabled="true"为 readonly="true";

转载于:https://www.cnblogs.com/startRuning/p/9437206.html

修改下面代码,让其只在管理员账号显示商务这个字条(可以通过v-if="$store.state.user.userInfo.businessFlag === 20"代码来判断当前账号是否为管理员账号,但请注意作用域)<!-- --> <template> <div class="table-main"> <div class="flex items-center justify-between"> <div class="flex gap-y-2"> <el-button size="mini" type="warning" v-verify="'root.members.membersBussiness.disable'" @click="stopItem"> 停用 </el-button> <el-button size="mini" type="primary" v-verify="'root.members.membersBussiness.enable'" @click="startItem"> 启动 </el-button> <el-button size="mini" type="primary" v-verify="'root.members.membersBussiness.user'" @click=" visible = !visible resetData('form') " > 添加客户 </el-button> <el-button size="mini" type="danger" v-verify="'root.members.membersBussiness.deleteBatch'" @click="delItem"> 删除 </el-button> <el-button size="mini" type="primary" v-verify="'root.members.membersBussiness.export'" url="/platform/user/export" v-export:userIdList="selected" > 导出 </el-button> <el-button size="mini" @click=" () => { if (selected.length == 0) return $message.warning('请选择数据') quickAxios('/qianhu/api/syncqianhu', 'POST', { ids: selected, paramType: 20 }) } " > 推送 </el-button> <!-- <el-button--> <!-- size="mini"--> <!-- type="primary"--> <!-- v-verify="'root.members.membersBussiness.addUserLabel'"--> <!-- @click="$refs.labelDialog.visible = true">--> <!-- 为选中客户标记标签--> <!-- </el-button>--> </div> <div class="dis-flex"> <!-- <div class="dis-flex" style="padding-right: 10px; white-space: nowrap; align-items: center">--> <!-- 所属商务:--> <!-- <el-input size="mini" v-model="searchForm.relationSaleName" @change="resetData('pages')"></el-input>--> <!-- </div>--> <j-search @change=" val => { params.queryType = Object.keys(val)[0] params.queryValue = val[Object.keys(val)[0]] resetData('pages') } " :options="selectList" /> </div> </div> <div class="mt-4"> <j-table v-loading="loading" :columns="columns" :pages.sync="pages" :total="total" :rows="list" data-key="userId" @pagesChange="getItem" select @select="val => (selected = val)" > <template #userLabelList="{ text }"> <div v-if="text" class="flex flex-wrap items-center gap-2"> <el-tag v-for="(item, index) of text" :key="index" size="small" class="!border-none" :style="{ 'background-color': item.labelColor }" effect="dark" > {{ item.labelName }} </el-tag> </div> </template> <template #masterFlag="{ row }"> <div v-if="accountTypeList.includes(10)"> {{ row.masterFlag ? '主账号' : '子账号' }} </div> <div v-else>{{ row.accountType == 20 ? '常规子账号' : '渠道账号' }}</div> </template> <template #userPackageList="{ text }"> <div v-if="text" class="flex flex-wrap items-center gap-2"> <el-tag class="!border-none" v-for="(item, index) of text" :key="index" size="small" effect="dark"> {{ item.packageLabelName }} </el-tag> </div> </template> <template #custom="{ row }"> <!-- <el-button type="text" @click=" form = { ...row } visible = true "> 编辑 </el-button> --> <el-button type="text" @click="viewItem(row.userId)" v-verify="'root.members.membersBussiness.edit'"> 编辑 </el-button> <el-button type="text" @click="getDitch(row)" v-verify="'root.members.membersBussiness.ditchTag'"> 渠道标签 </el-button> <el-button type="text" @click="getPackTag(row)" v-verify="'root.members.membersBussiness.packTag'"> 包装标签 </el-button> </template> </j-table> </div> <j-dialog v-model="isShow" title="账户详情" width="1200px" cancel="关闭" @cancel="getItem" height="490px"> <account-details ref="details" v-if="isShow" type="company" :params="{ userId }"></account-details> </j-dialog> <j-dialog v-model="visible" title="新增/编辑客户" cancel confirm @ok="sendForm"> <div class="flex items-center mb-4"> <div class="w-[135px] text-right pr-3">账户类型:</div> <div> <el-radio v-model="userType" :label="10" v-if="accountTypeList.includes(10)">主账号</el-radio> <el-radio v-model="userType" :label="20" v-else>子账号</el-radio> </div> </div> <template v-if="userType == 10"> <j-form-auto :config="config" label-width="135px" size="small" v-model="form" ref="form"> <template #levelId> <el-form-item label="客户等级:" prop="levelId" :rules="[{ required: true, message: '请选择客户等级', trigger: 'blur' }]" > <j-dict-select class="w-[220px]" :defOptions="levelList" value-key="id" value-label="levelName" v-model="form.levelId" ></j-dict-select> </el-form-item> </template> <template #storeHouseId="{ item }"> <el-form-item :label="item.label + ':'" prop="storeHouseId" :rules="[{ required: true, message: '请选择仓库', trigger: 'blur' }]" > <el-button @click="$refs.depot.isShow = true" type="primary" size="mini">选择仓库</el-button> <el-tag effect="plain" class="ml-4" v-if="form.storeHouseName"> {{ form.storeHouseName }} </el-tag> </el-form-item> </template> </j-form-auto> <j-form-auto :config="extendConfig" v-model="form.extendInfo" label-width="135px" size="small" ref="extendForm"> <template #mallOrganId> <el-form-item label="归属管理组织:" prop="mallOrganId"> <el-cascader ref="cascader" :props="{ checkStrictly: true, value: 'id', label: 'organName', children: 'childrenList', }" :value="[form.extendInfo.mallGroupId, form.extendInfo.mallOrganId]" :options="organTree" @change="selectChart" ></el-cascader> </el-form-item> </template> <template #relationSaleId> <el-form-item label="商务:" prop="relationSaleId"> <el-button type="primary" size="mini" @click="$refs.relation.isShow = true">绑定商务</el-button> <el-tag type="primary" class="ml-4" size="small" v-if="form.extendInfo.relationSaleName"> {{ form.extendInfo.relationSaleName }} </el-tag> </el-form-item> </template> </j-form-auto> <j-form-auto :config="comConfig" v-model="form.corpInfo" label-width="135px" size="small" ref="comForm"> <template #legalInfoCertList="{ item }"> <el-form-item :label="item.label + ':'" prop="legalInfoCertList" :rules="item.rules"> <div class="flex items-center gap-3"> <div class="flex-col flex-center" v-for="(item, index) of form.corpInfo.legalInfoCertList" :key="index" > <j-upload v-model="item.certFileUrl" :limit="1" serialize /> <div class="mt-2 text-xs text-neutral-500">{{ item.certName }}</div> </div> </div> </el-form-item> </template> <el-form-item label="所在地址:" prop="" :rules="[ { required: true, message: '请选择地址', trigger: ['change', 'blur'], }, { validator: (rule, e, callback) => { const value = this.form.extendInfo console.log(value) if (value) { if (!value.province) { callback(new Error('请选择省份')) return } if (!value.city) { callback(new Error('请选择城市')) return } if (!value.county) { callback(new Error('请选择区/县')) return } callback() } else { callback(new Error('省份')) } }, trigger: 'blur', }, ]" > <j-address :attrs="{ province: { disabled: false }, city: { disabled: false }, }" class="!grid !grid-cols-3 [&_.el-select]:block" @change="onChangeArea" ></j-address> </el-form-item> </j-form-auto> </template> <template v-else> <j-form-auto :config="sonConfig" label-width="135px" size="small" v-model="form" ref="sonForm"> <template #masterId> <el-form-item label="所属主账号:" prop="masterId" :rules="[{ required: true, message: '请选择主账号', trigger: 'blur' }]" > <el-button type="primary" @click="$refs.user.isShow = true">绑定主账号</el-button> <div>{{ form.masterName }}</div> </el-form-item> </template> </j-form-auto> </template> </j-dialog> <label-dialog ref="labelDialog" :userIdList="selected" @closeDialog=" $refs.labelDialog.visible = false getItem() " ></label-dialog> <j-dialog ref="channel" title="标记渠道标签" cancel confirm @ok="val => quickAxios(`/platform/user/channel/save/${userId}`, 'POST', { channelList }, val)" > <j-dict-multiple v-if="masterFlag" type="checkbox" size="small" key="master" :value="form.channelIdList" value-key="id" @change=" val => { channelList = val.map(item => { return { channelName: item.itemName, channelId: item.id } }) } " dictCode="10007" ></j-dict-multiple> <j-dict-multiple v-else-if="channels.length && row.accountType != 20" type="checkbox" size="small" json key="son" value-key="channelId" value-label="channelName" :value="channelList" @change="val => (channelList = val)" :defOptions="channels" ></j-dict-multiple> <div v-else>该账户暂无关联渠道</div> </j-dialog> <j-dialog ref="packaging" title="标记包装标签" cancel confirm @ok="setPackTag"> <div v-if="masterFlag"> <el-button type="primary" size="mini" @click="$refs.packTag.isShow = true">添加</el-button> </div> <table class="mt-4"> <tr> <th>标签名称</th> <th>标签可选包装</th> </tr> <tr v-for="(item, index) of packList" :key="index"> <td> {{ item.itemName }} </td> <td> <template v-if="item.itemExtend"> <el-checkbox :disabled="ele.disabled" v-for="(ele, i) of item.itemExtend" :key="i" :true-label="10" :false-label="20" v-model="ele.checkedFlag" > {{ ele.itemName }} </el-checkbox> </template> </td> </tr> </table> </j-dialog> <j-dialog ref="packTag" title="选择包装标签" cancel confirm @ok=" packList = $refs.packList.idList.map(item => { return { ...item, itemExtend: JSON.parse(item.itemExtend) } }) $refs.packTag.isShow = false " > <pack-tag ref="packList"></pack-tag> </j-dialog> <relation-list ref="relation" :params="{ businessFlag: 10, organId: form.extendInfo.mallOrganId }" @change=" val => { form.extendInfo.relationSaleId = val.id form.extendInfo.relationSaleName = val.loginAccount } " ></relation-list> <j-dialog ref="depot" width="1200px" title="选择仓库" cancel confirm @ok="$refs.depot.isShow = false"> <goods-depot ref="goodsDepot" class="!p-0" radio @radioChange=" val => { form.storeHouseId = val.id form.storeHouseName = val.storeHouseName } " ></goods-depot> </j-dialog> <user-list :params="{ accountTypeList: [10], userType: 20 }" ref="user" json @change=" val => { form.masterName = val.loginAccount form.masterId = val.userId $refs.user.isShow = false } " ></user-list> </div> </template> <script> import jSearch from '@/components/j-search.vue' import AccountDetails from '../AccountDetails.vue' import LabelDialog from './labelDialog.vue' import packTag from '../../category/packTag.vue' import UserList from '@/components/user-list.vue' import RelationList from '@/components/relation-list.vue' import JUpload from '@/components/j-upload.vue' import GoodsDepot from '../../commodity/goodsDepot.vue' import JAddress from '@/components/j-address.vue' // import引入的组件需要注入到对象中才能使用 export default { props: { accountTypeList: { type: Array, default: () => [], }, }, components: { jSearch, AccountDetails, LabelDialog, packTag, UserList, RelationList, JUpload, GoodsDepot, JAddress }, data() { // 这里存放数据 return { loading: true, row: {}, // 组织集合 organTree: [], // 已选渠道标签 channelList: [], // 渠道标签集合 channels: [], // 包装标签集合 packList: [], params: { userType: 20 }, userInfo: {}, pages: { pageNum: 1, pageSize: 10, }, userType: this.accountTypeList.includes(10) ? 10 : 20, userId: '', isShow: false, visible: false, masterFlag: false, searchForm: { relationSaleName: '', }, form: { levelId: '', accountType: 20, storeHouseId: '', storeHouseName: '', masterName: '', corpInfo: { legalInfoCertList: [], }, extendInfo: { relationSaleName: '', mallOrganId: '', relationSaleId: '', }, }, list: [], config: [ { label: '用户名', name: 'loginAccount', type: 'input', required: true, attrs: { maxlength: 50, 'show-word-limit': true, }, }, { label: '密码', name: 'loginPwd', type: 'input', required: true, rules: [{ type: 'password' }] }, { label: '确认密码', name: 'userPwdCfm', type: 'input', required: true, rules: [ { validator: (rule, value, callback) => { if (value === '') { callback(new Error('请输入密码')) } else if (value != this.form.loginPwd) { callback(new Error('两次密码输入不一致')) } else { callback() } }, trigger: 'blur', }, ], }, { label: '手机号', name: 'phone', type: 'phone', required: true, rules: [{ type: 'phone' }] }, { label: '客户等级', name: 'levelId' }, { label: '客户生日', name: 'extendInfo.birthday', type: 'date' }, { required: true, label: '仓库', name: 'storeHouseId' }, ], extendConfig: [ { label: '归属组织', name: 'mallOrganId', type: 'input', required: true }, { label: '商务', name: 'relationSaleId', type: 'input', required: true }, ], comConfig: [ { label: '企业名称', name: 'corpName', type: 'input', required: true }, { label: '统一信用社代码', name: 'unifiedSocialCreditCode', type: 'input', required: true, rules: [{ type: 'creditCode' }], }, { label: '法定代表人', name: 'personName', type: 'input', required: true }, { label: '公司电话', name: 'corpPhone', type: 'phone', required: true, rules: [{ type: 'phone' }], }, { label: '公司网站', name: 'corpSite', type: 'input' }, { label: '企业类型', name: 'corpTypeId', type: 'dictCode', dictCode: 60001, attrs: { 'value-key': 'id' }, }, { label: '证照类型 ( 信息 )', name: 'legalInfoCertList', required: true, rules: [ { validator: (rule, value, callback) => { if (value && value.length) { const flag = value.find(item => { if (item.isNeed == 10) { return !!item.certFileUrl } else { return true } }) if (!flag) { callback(new Error('请上传营业执照')) } else { callback() } } else { callback(new Error('请上传营业执照')) } }, trigger: 'blur', }, ], }, ], sonConfig: [ { label: '子账号类型', name: 'accountType', type: 'radio-group', options: [ { label: '常规子账号', value: 20 }, { label: '渠道账号', value: 25 }, ], required: true, }, { name: 'masterId', }, { label: '用户名', name: 'loginAccount', type: 'input', required: true }, { label: '手机号', name: 'phone', type: 'phone', required: true, rules: [{ type: 'phone' }] }, { label: '密码', name: 'loginPwd', type: 'input', required: true }, { label: '邮箱', name: 'email', type: 'input', rules: [{ type: 'email' }], required: true }, ], selected: [], levelList: [], selectList: [ { label: '用户名', value: '10' }, { label: '手机号', value: '15' }, { label: '邮箱', value: '20' }, { label: '主账号', value: '25' }, { label: '真实姓名', value: '30' }, { label: '公司名称', value: '35' }, { label: '所属商务', value: '40' }, ], columns: [ // { label: '标签', name: 'userLabelList', width: 150 }, { label: '包装标签', name: 'userPackageList', width: 150 }, { label: '用户名', name: 'loginAccount' }, { label: '所属主账号', name: 'masterLoginAccount', hidden: this.accountTypeList.includes(10) }, // { label: '客户类型', name: 'userType', custom: val => (val == 10 ? '零售' : '企业客户') }, { label: '企业名称', name: 'legalName' }, { label: '账户类型', name: 'masterFlag', hidden: this.accountTypeList.includes(10) }, { label: '邮箱', name: 'email' }, { label: '手机号', name: 'phone' }, { label: '商务', name: 'extendInfo', custom: val => val.relationSaleName }, { label: '地区', name: 'extendInfo', custom: val => val.realAddress }, //{ label: '生日', name: 'extendInfo', custom: val => val.birthday }, { label: '创建时间', name: 'cdate' }, { label: '性别', name: 'extendInfo', custom: val => this.sexType[val.sex] || '未知' }, // { label: '注册IP', name: 'registerIp' }, { label: '状态', name: 'state', custom: val => (val == 10 ? '可用' : '禁用') }, { label: '操作', name: 'custom', width: '250px', fixed: 'right' }, ], total: 0, sexType: { 10: '男', 20: '女', 30: '未知', }, } }, watch: { 'form.corpInfo.corpTypeId': { handler(val) { Request.GET(`/platform/corpRelation/cert/listByCorpType/${val}`, {}, res => { if (res.code == 200) { this.form.corpInfo.legalInfoCertList = res.data.map(item => { return { ...item, certFileUrl: '', } }) } }) }, }, }, // 监听属性 类似于data概念 computed: { // 请求的包装标签字段 }, // 生命周期 - 创建完成(可以访问当前this实例) created() { this.getItem() Request.GET(`/platform/userLeveDict/listLevel`, { levelUserType: 20 }, res => { if (res.code == 200) { this.levelList = res.data } }) Request.GET(`/platadmin/organ/ztree`, {}, res => { if (res.code == 200) { res.data.forEach(item => { item.childrenList.forEach(ele => { ele.childrenList = [] }) }) this.organTree = this.getCascader(res.data) } }) }, // 生命周期 - 挂载完成(可以访问DOM元素) mounted() {}, // 方法集合 methods: { onChangeArea(e) { let form = { ...this.form.extendInfo } form = Object.assign({}, form, e) form.cityText = e.city form.city = e.cityCode form.countyText = e.county form.county = e.countyCode form.provinceText = e.province form.province = e.provinceCode this.form.extendInfo = form }, // 选择组织 selectChart(val) { this.form.extendInfo.mallGroupId = val[0] this.form.extendInfo.mallOrganId = val[1] const row = this.$refs['cascader'].getCheckedNodes()[0] this.form.extendInfo.mallGroupName = row.pathLabels[0] this.form.extendInfo.mallOrganName = row.pathLabels[1] }, // 获取关联的渠道 async getDitch(row) { this.masterFlag = row.masterFlag this.row = row this.channelList = [] if (!row.masterFlag) { Request.GET(`/platform/user/details/${row.masterId}`, {}, res => { this.channels = res.data.channelList || [] Request.GET(`/platform/user/channel/list/${row.userId}`, {}, res => { this.$nextTick(() => { this.channelList = res.data || [] }) }) }) } else { this.form = { ...row } } this.$refs.channel.isShow = true this.userId = row.userId this.$forceUpdate() }, // 获取关联的包装标签 async getPackTag(row) { this.masterFlag = row.masterFlag if (!row.masterFlag) { Request.GET(`/platform/user/details/${row.masterId}`).then(res => { Request.GET(`/platform/user/packageLabel/list/${row.userId}`, {}, ({ data }) => { const selected = [] const userPackageList = res.data.userPackageList || [] data.forEach(item => { item.packageList.forEach(ele => { if (ele.checkedFlag == 10) { selected.push(ele.itemId) } }) }) this.$refs.packaging.isShow = true this.userId = row.userId userPackageList.forEach(item => { item.packageList.forEach(ele => { if (ele.checkedFlag == 10) { ele.disabled = false } else { ele.disabled = true } if (selected.includes(ele.itemId)) { ele.checkedFlag = 10 } else { ele.checkedFlag = 20 } }) }) this.packList = userPackageList.map(item => { return { itemName: item.packageLabelName, itemId: item.packageLabelId, itemExtend: item.packageList, } }) }) }) } else { Request.GET(`/platform/user/packageLabel/list/${row.userId}`, {}, res => { this.$refs.packaging.isShow = true this.userId = row.userId this.packList = res.data && res.data.map(item => { return { itemName: item.packageLabelName, itemId: item.packageLabelId, itemExtend: item.packageList, } }) }) } }, setPackTag() { const itemList = this.packList.map(item => { const packageList = [] item.itemExtend.forEach(ele => { packageList.push({ itemId: ele.itemId, itemName: ele.itemName, checkedFlag: ele.checkedFlag == 10 ? 10 : 20, }) }) return { packageLabelId: item.itemId, packageLabelName: item.itemName, packageList, } }) Request.POST(`/platform/user/packageLabel/save/${this.userId}`, { itemList }, res => { if (res.code == 200) { this.$refs.packaging.isShow = false this.getItem() this.$message.success('保存成功') } }) }, startItem() { if (!this.selected.length) return this.$message.warning('请选择数据') Request.POST('/platform/user/updateUserState/10', { idList: this.selected }, res => { if (res.code == 200) { this.getItem() this.$message.success('启用成功') } }) }, stopItem() { if (!this.selected.length) return this.$message.warning('请选择数据') Request.POST('/platform/user/updateUserState/20', { idList: this.selected }, res => { if (res.code == 200) { this.getItem() this.$message.success('禁用成功') } }) }, delItem() { if (!this.selected.length) return this.$message.warning('请选择数据') Request.POST('/platform/user/deleteBatch', { idList: this.selected }, res => { if (res.code == 200) { this.getItem() this.$message.success('删除成功') } }) }, sendForm() { const form = { ...this.form } if (this.userType == 10) { this.$refs.form.submit().then(_ => { this.$refs.extendForm.submit().then(_ => { this.$refs.comForm.submit().then(_ => { if (this.form.userId) { Request.POST(`/platform/user/update/${this.form.userId}`, { ...form }, res => { if (res.code == 200) { this.visible = false this.getItem() this.$message.success('编辑成功') } }) } else { Request.POST('/platform/user/add', { ...form }, res => { if (res.code == 200) { this.visible = false this.getItem() this.$message.success('新增成功') } }) } }) }) }) } else { this.$refs.sonForm.submit().then(_ => { Request.POST('/platform/user/subAccount/add', { ...form }, res => { if (res.code == 200) { this.visible = false this.getItem() this.$message.success('新增成功') } }) }) } }, viewItem(id) { this.userId = id this.isShow = true }, getItem() { this.loading = true Request.POST( '/platform/user/pageList', { ...this.pages, ...this.params, accountTypeList: this.accountTypeList, ...this.searchForm, checkState: this.accountTypeList.includes(25) ? 20 : '', }, res => { this.loading = false if (res.code == 200) { this.list = res.data.content this.total = res.data.total } } ) }, }, } </script> <style lang="scss" scoped> //@import url(); 引入公共css类 table { border-collapse: collapse; } table, th, td { font-weight: 400; border: 1px solid #dcdfe6; padding: 8px 16px; } </style>
06-06
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>积分商城网厅常见问题分类配置</title> <script src="../js/jquery-1.min.js"></script> <script src="../js/bootstrap.min.js"></script> <link href="../css/bootstrap.min.css" rel="stylesheet"> <script src="../js/lay.js"></script> <!-- 添加 TinyMCE 引用 --> <script src="../js/tinymce/tinymce.min.js"></script> <style> /* 添加编辑器样式调整 */ .tox-tinymce { border-radius: 4px !important; border: 1px solid #dcdfe6 !important; } /* 隐藏原始文本区域 */ #content { display: none; } </style> </head> <style> body { font-family: "Microsoft YaHei", Arial, sans-serif; max-width: 1400px; margin: 30px auto; padding: 20px; background-color: #f8f9fa; } .hidden-id { display: none; } .form-container { background-color: white; padding: 40px; border-radius: 10px; box-shadow: 0 2px 12px rgba(0,0,0,0.08); } .form-section { border: 1px solid #ebeef5; padding: 20px; margin-bottom: 25px; border-radius: 8px; background: #fafafa; } .form-section h3 { color: #409eff; margin: 0 0 20px 0; padding-bottom: 10px; border-bottom: 1px solid #ebeef5; font-size: 16px; } .table { width: 100%; border-collapse: collapse; margin-bottom: 20px; } .table th, .table td { padding: 12px 15px; border: 1px solid #ddd; text-align: left; } .table th { background-color: #f5f5f5; font-weight: 600; } .table tr:nth-child(even) { background-color: #f9f9f9; } .table tr:hover { background-color: #f1f1f1; } .btn { padding: 6px 12px; border-radius: 4px; cursor: pointer; font-size: 14px; border: none; transition: all 0.3s; display: inline-flex; align-items: center; justify-content: center; } .btn-primary { background-color: #409eff; color: white; } .btn-primary:hover { background-color: #66b1ff; } .btn-success { background-color: #67c23a; color: white; } .btn-success:hover { background-color: #85ce61; } .btn-danger { background-color: #f56c6c; color: white; } .btn-danger:hover { background-color: #f78989; } .btn-sm { padding: 4px 8px; font-size: 12px; } .modal { display: none; position: fixed; z-index: 1000; left: 0; top: 0; width: 100%; height: 100%; overflow: auto; background-color: rgba(0,0,0,0.4); } .modal-content { background-color: #fefefe; margin: 10% auto; padding: 20px; border: 1px solid #888; width: 50%; border-radius: 8px; } .close { color: #aaa; float: right; font-size: 28px; font-weight: bold; cursor: pointer; } .close:hover { color: black; } .form-group { margin-bottom: 15px; } .form-group label { display: block; margin-bottom: 5px; font-weight: 600; color: #606266; } .form-control { width: 100%; padding: 8px 12px; border: 1px solid #dcdfe6; border-radius: 4px; box-sizing: border-box; } textarea.form-control { height: auto; min-height: 100px; } .required label::before { content: "*"; color: #f56c6c; margin-right: 4px; } .child-node { padding-left: 30px; background-color: #f9f9f9; vertical-align: middle; } .submit-btn { display: block; width: 200px; margin: 20px auto 0; padding: 10px; background: #409eff; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 14px; transition: all 0.3s; } .submit-btn:hover { background: #66b1ff; } .action-buttons { text-align: left; /* 内容左对齐 */ } .action-buttons button { display: inline-block; margin-right: 5px; /* 按钮之间的间距 */ vertical-align: middle; /* 垂直居中 */ } .table th:nth-child(4), .table td:nth-child(4) { width: 15%; /* 与表头设置一致 */ min-width: 180px; /* 设置最小宽度防止内容挤压 */ white-space: nowrap; /* 防止内容换行 */ } </style> <body> <div class="form-container"> <div class="form-section"> <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px;"> <h3 style="margin: 0 auto;">常见问题分类配置</h3> <button id="addTopCategory" class="btn btn-primary">添加一级分类</button> </div> <table class="table" id="categoryTable"> <thead> <tr> <th width="15%">分类名称</th> <th width="50%">分类内容</th> <th width="5%">排序</th> <th width="30%">操作</th> </tr> </thead> <tbody id="categoryList"> <!-- 动态加载数据 --> </tbody> </table> </div> </div> <!-- 添加/编辑分类的模态框 --> <div id="categoryModal" class="modal"> <div class="modal-content"> <span class="close">×</span> <h3 id="modalTitle">添加分类</h3> <form id="categoryForm" novalidate> <input type="hidden" id="id" name="id"> <input type="hidden" id="pid" name="pid" value="0"> <div class="form-group required"> <label for="name">分类名称:</label> <input type="text" class="form-control" id="name" name="name" placeholder="请输入分类名称,同级别不允许重复" required> </div> <div class="form-group required" id="contentGroup"> <label for="content">分类内容:</label> <textarea class="form-control" id="content" name="content" placeholder="请输入分类描述" required></textarea> </div> <div class="form-group required"> <label for="orderNum">排序顺序: <span style="color: #888; font-size: 12px; margin-left: 5px;">越小越靠前,请输入正整数</span> </label> <input type="number" class="form-control" id="orderNum" name="orderNum" placeholder="请输入分类排序,同级别不允许重复" required min="1" step="1"> </div> <button type="submit" class="submit-btn">保存</button> </form> </div> </div> <script> // 动态设置 required 的函数 function setContentRequired(required) { if (required) { $('#content').attr('required', 'required'); $("#contentGroup").removeClass("hidden"); tinymce.get('content').show(); $('#content').css({visibility: 'visible', position: 'static'}); // 移除隐藏样式 } else { $('#content').removeAttr('required'); $("#contentGroup").addClass("hidden"); tinymce.get('content').hide(); $('#content').css({visibility: 'hidden', position: 'absolute', left: '-9999px'}); // 恢复隐藏样式 } } $(document).ready(function() { // 初始化 TinyMCE tinymce.init({ license_key: 'gpl', // 对于GPL许可证 selector: '#content', language: 'zh_CN', language_url: '../js/tinymce/langs/zh_CN.js', height: 300, plugins: 'link lists image table code help wordcount', toolbar: 'undo redo | formatselect | image | bold italic | alignleft aligncenter alignright | bullist numlist outdent indent | link image | code help', images_upload_url: '../point/uploadFileNew?limit=010', images_upload_handler: function (blobInfo, progress) { return new Promise((resolve, reject) => { const formData = new FormData(); formData.append('file', blobInfo.blob(), blobInfo.filename()); // 显示上传进度 progress(0); $.ajax({ url: tinymce.activeEditor.settings.images_upload_url, type: 'POST', data: formData, processData: false, contentType: false, xhr: function() { const xhr = $.ajaxSettings.xhr(); if (xhr.upload) { xhr.upload.addEventListener('progress', function(e) { if (e.lengthComputable) { progress((e.loaded / e.total) * 100); } }); } return xhr; }, success: function(response) { if (response.state === '200') { resolve(response.filePath); // 传递图片 URL 给编辑器 } else { $.MsgBox.Alert("上传失败", response.msg || "未知错误"); reject(response.msg); } }, error: function(xhr) { $.MsgBox.Alert("上传失败", "网络错误:" + xhr.statusText); reject("网络错误:" + xhr.statusText); } }); }); }, skin: 'oxide', content_css: 'default', menubar: false, branding: false, relative_urls: false, remove_script_host: false, setup: function(editor) { editor.on('init', function() { console.log('TinyMCE 初始化成功'); }); editor.on('error', function(e) { console.error('TinyMCE 错误:', e); }); editor.on('change', function() { // 内容变化时的逻辑(如实时保存) }); }, valid_elements: 'p,br,strong/b,em/i,u,ol,ul,li,h1,h2,h3,h4,a[href|target=_blank],img[src|alt|title|width|height|class]', valid_children: '-p[strong/b|em/i|u|a|img],-li[p|ol|ul]', extended_valid_elements: '', invalid_elements: 'script,iframe,object,embed,form,input,textarea,button,select,option,style', content_security_policy: "default-src 'self'; img-src 'self' data:; media-src 'none'; script-src 'none';", forced_root_block: 'p', force_br_newlines: false, convert_newlines_to_brs: false, remove_linebreaks: false, // 允许的CSS类 valid_classes: { '*': 'text-left,text-center,text-right,text-justify' }, // 粘贴过滤设置 paste_as_text: false, paste_postprocess: function(editor, node) { // 额外的粘贴后处理 }, init_instance_callback: function(editor) { console.log('Editor完全初始化完成:', editor.id); } }); // 加载分类数据 loadCategoryData(); // 打开添加一级分类模态框 $("#addTopCategory").click(function() { $("#modalTitle").text("添加一级分类"); $("#categoryForm")[0].reset(); $("#id").val(""); $("#pid").val("0"); $("#content").removeAttr("required"); $("#contentGroup").addClass("hidden"); tinymce.get('content').hide(); $("#categoryModal").show(); setContentRequired(false); }); // 添加 orderNum 输入限制 $("#orderNum").on('input', function() { let value = parseInt($(this).val()) || 0; if (value < 1) { $(this).val(1); } }); // 关闭模态框 $(".close").click(function() { $("#categoryModal").hide(); tinymce.get('content').setContent(''); }); // 点击模态框外部关闭 $(window).click(function(event) { if (event.target == $("#categoryModal")[0]) { $("#categoryModal").hide(); tinymce.get('content').setContent(''); } }); // 提交表单 $("#categoryForm").submit(function(e) { e.preventDefault(); // 验证分类名称不能为空 var name = $("#name").val().trim(); if (name === '') { $.MsgBox.Alert("提示", "分类名称不能为空"); $("#name").focus(); // 聚焦到输入框 return; } // 验证分类内容(如果是必填的) if ($("#content").is(':required') && tinymce.get('content').getContent().trim() === '') { $.MsgBox.Alert("提示", "分类内容不能为空"); tinymce.get('content').focus(); // 聚焦到编辑器 return; } // 同步编辑器内容到 textarea var content = tinymce.get('content').getContent(); $('#content').val(content); saveCategory(); }); }); // 加载分类数据 function loadCategoryData() { $.ajax({ url: "../problemClassification/list", type: "GET", dataType: "json", success: function(data) { renderCategoryTable(data); }, error: function() { $.MsgBox.Alert("提示", "加载分类数据失败"); } }); } // 渲染分类表格 function renderCategoryTable(data) { var html = ""; $.each(data, function(index, item) { html += '<tr data-id="' + item.id + '">'; html += ' <td class="hidden-id">' + item.id + '</td>'; // 隐藏的ID列 html += ' <td>' + item.name + '</td>'; html += ' <td>' + (item.content || '') + '</td>'; // 新增内容列 html += ' <td>' + (item.orderNum || 0) + '</td>'; html += ' <td class="action-buttons">'; html += ' <button class="btn btn-primary btn-sm edit-btn" data-id="' + item.id + '">编辑</button>'; html += ' <button class="btn btn-success btn-sm add-child-btn" data-id="' + item.id + '">添加子类</button>'; html += ' <button class="btn btn-danger btn-sm delete-btn" data-id="' + item.id + '">删除</button>'; html += ' </td>'; html += '</tr>'; // 添加子分类 if (item.chilsNode && item.chilsNode.length > 0) { $.each(item.chilsNode, function(i, child) { html += '<tr class="child-node" data-id="' + child.id + '">'; html += ' <td class="hidden-id">' + child.id + '</td>'; // 隐藏的ID列 html += ' <td>└ ' + child.name + '</td>'; html += ' <td>' + (child.content || '') + '</td>'; // 新增内容列 html += ' <td>' + (child.orderNum || 0) + '</td>'; html += ' <td class="action-buttons">'; html += ' <button class="btn btn-primary btn-sm edit-btn" data-id="' + child.id + '">编辑</button>'; html += ' <button class="btn btn-danger btn-sm delete-btn" data-id="' + child.id + '">删除</button>'; html += ' </td>'; html += '</tr>'; }); } }); $("#categoryList").html(html); // 绑定按钮事件 $(".edit-btn").click(function() { var id = $(this).data("id"); editCategory(id); }); // 添加子分类按钮点击事件 $(".add-child-btn").click(function() { var pid = $(this).data("id"); $("#modalTitle").text("添加子分类"); $("#categoryForm")[0].reset(); $("#id").val(""); $("#pid").val(pid); $("#content").attr("required", true); $("#contentGroup").removeClass("hidden"); tinymce.get('content').show(); // 显示编辑器 $("#categoryModal").show(); setContentRequired(true); }); $(".delete-btn").click(function() { var id = $(this).data("id"); $.MsgBox.Confirm("提示", "确定要删除这个分类吗?", function() { deleteCategory(id); }); }); } // 编辑分类 function editCategory(id) { $("#modalTitle").html("编辑分类 <small>(加载中...)</small>"); // 先确保编辑器实例存在 if (!tinymce.get('content')) { console.error('TinyMCE 编辑器未初始化'); $.MsgBox.Alert("温馨提示", "编辑器初始化失败,请刷新页面重试"); return; } $.ajax({ url: "../problemClassification/get/" + id, type: "GET", dataType: "json", success: function(data) { $("#modalTitle").text("编辑分类"); $("#id").val(data.id); $("#name").val(data.name); $("#orderNum").val(data.orderNum); $("#pid").val(data.pid); // 确保编辑器可见性正确 if(data.pid == 0) { setContentRequired(false); } else { setContentRequired(true); } // 延迟设置内容以确保编辑器就绪 setTimeout(function() { try { tinymce.get('content').setContent(data.content || ''); $("#categoryModal").show(); } catch(e) { console.error('设置编辑器内容失败:', e); $.MsgBox.Alert("温馨提示", "编辑器内容设置失败,请重试"); } }, 100); }, error: function() { $.MsgBox.Alert("温馨提示", "获取分类信息失败"); } }); } // 保存分类 function saveCategory() { // 获取提交按钮,并禁用 + 修改文字 var $submitBtn = $("#categoryForm").find("button[type='submit']"); $submitBtn.prop("disabled", true).text("保存中..."); // 强制同步 TinyMCE 内容到 textarea tinymce.get('content').save(); // 自定义验证 if ($("#content").is(':required') && tinymce.get('content').getContent().trim() === '') { $.MsgBox.Alert("温馨提示", '分类内容不能为空'); $submitBtn.prop("disabled", false).text("保存"); // 恢复按钮状态 return false; } // 新增 orderNum 校验 const orderNum = parseInt($("#orderNum").val()); if (isNaN(orderNum) || orderNum < 1) { $.MsgBox.Alert("温馨提示", "排序顺序必须为正整数"); $submitBtn.prop("disabled", false).text("保存"); // 恢复按钮状态 return false; } var formData = $("#categoryForm").serialize(); var url = $("#id").val() ? "../problemClassification/update" : "../problemClassification/add"; $.ajax({ url: url, type: "POST", data: formData, success: function(response) { if (response === "添加成功" || response === "更新成功") { $("#categoryModal").hide(); loadCategoryData(); } else { $.MsgBox.Alert("温馨提示", response); } }, error: function() { $.MsgBox.Alert("温馨提示", "操作失败"); }, complete: function() { // 无论成功或失败,最终恢复按钮状态 $submitBtn.prop("disabled", false).text("保存"); } }); } // 删除分类 function deleteCategory(id) { $.ajax({ url: "../problemClassification/delete/" + id, type: "POST", success: function(response) { if(response === "删除成功") { loadCategoryData(); } else { $.MsgBox.Alert("温馨提示", response); } }, error: function() { $.MsgBox.Alert("温馨提示", "删除失败"); } }); } </script> </body> </html> 分下一下,上传图片报错:Cannot read properties of undefined(reading 'images_upload_url')
06-19
<%@ page import="util.DbConnet" %> <%@ page import="java.sql.ResultSet" %> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <% //功能:通过编号获取用户要编辑的具体数据 //1.接收传过来的编号 String id = request.getParameter("appliance_type"); //通过编号执行查询 String sql = "select * from `living_room_appliances` where `appliance_type`=?;"; Object[] params = new Object[]{ id }; ResultSet rs = DbConnet.select(sql, params);//真正执行查询,获得查询结果的数据集 //验证查询结果是否有数据(处理的是无数据情况) if(!rs.next()) response.sendRedirect("list.jsp"); %> <html> <head> <title>编辑用户</title> <link rel="stylesheet" href="../css/common.css"> <link rel="stylesheet" href="../css/add.css"> </head> <body> <%--编辑: 1.点击编辑按钮,打开一个页面 2.新编辑页面需要包含: (1)表单 (2)输入框:账号、密码、确认密码、姓名 (3)按钮:保存(提交)、重置、返回 3.功能: 保存(提交):无刷新提交表单中的所有数据 重置:还原表单中的内容为初始状态 返回:重新打开列表页面(list.jsp) --%> <header> <div class="title">编辑用户</div> </header> <div class="main"> <form id="editForm"> <input type="hidden" name="id" value="<%=id%>"> <div class="form-item"> <label for="appliance_name">家电类型:</label> <%-- disabled:禁用元素(数据不传输) readonly:只读(不能编辑,可以传输) --%> <input disabled value="<%=rs.getString("appliance_type")%>" id="appliance_name" name="appliance_name" type="text"> </div> <div class="form-item"> <label for="realname">家电名称:</label> <input value="<%=rs.getString("appliance_name")%>" id="realname" name="realname" type="text"> </div> <div class="form-item"> <button class="primary" id="btnSubmit" type="button">保存</button> <button type="reset">重置</button> <button id="btnBack" type="button">返回</button> </div> </form> </div> <script src="../js/jquery-3.5.1.min.js"></script> <script src="../js/common.js"></script> <script> //绑定保存按钮的点击事件 $('#btnSubmit').on('click', function () { //1.验证不能为空:账号、密码、姓名 if(!checkInputIsNull('#username','账号')) return false; if(!checkInputIsNull('#password','密码')) return false; //比较两次输入的密码是否一致 //2.无刷新提交数据 postAction("/room/livinggedit", $('#editForm').serialize(),function (res) { //1.弹出提示信息 alert(res.msg); //2.成功后返回列表页面(list.jsp) if(res.result) window.location.href = res.url; }); }); //绑定返回按钮的点击事件 $('#btnBack').on('click', function () { if(confirm("确定要返回吗?")){ window.location.href='livingroom.jsp'; } }); </script> </body> </html>
最新发布
07-06
{ "msg": "操作成功", "code": 0, "data": [ { "path": "D:\\", "name": ".. (上级目录)" }, { "path": "D:\\kettle\\ETL_SYS_DY", "name": "ETL_SYS_DY" }, { "path": "D:\\kettle\\GD_ETL2", "name": "GD_ETL2" }, { "path": "D:\\kettle\\pdi-ce-8.2.0.0-342", "name": "pdi-ce-8.2.0.0-342" }, { "path": "D:\\kettle\\pims_etl", "name": "pims_etl" }, { "path": "D:\\kettle\\pims_etl - 副本", "name": "pims_etl - 副本" }, { "path": "D:\\kettle\\pims_etl_jndi", "name": "pims_etl_jndi" }, { "path": "D:\\kettle\\plasmOutAndSampleOut", "name": "plasmOutAndSampleOut" }, { "path": "D:\\kettle\\PSFK_ETL_SYS_DAILY_INCREMENT", "name": "PSFK_ETL_SYS_DAILY_INCREMENT" }, { "path": "D:\\kettle\\test", "name": "test" }, { "path": "D:\\kettle\\uploadPath", "name": "uploadPath" } ] } <!DOCTYPE html> <html lang="zh" xmlns:th="http://www.thymeleaf.org"> <head> <th:block th:include="include :: header('新增资源库')"/> <th:block th:include="include :: datetimepicker-css"/> </head> <body class="white-bg"> <div class="wrapper wrapper-content animated fadeInRight ibox-content"> <form class="form-horizontal m" id="form-repository-add"> <div class="form-group"> <label class="col-sm-3 control-label">资源库名称:</label> <div class="col-sm-8"> <input name="repoName" class="form-control" type="text"> </div> </div> <!--<div class="form-group"> <label class="col-sm-3 control-label">当资源库类型是db时候的用户名:</label> <div class="col-sm-8"> <input name="repoUsername" class="form-control" type="text"> </div> </div> <div class="form-group"> <label class="col-sm-3 control-label">当资源库类型是db时候的密码:</label> <div class="col-sm-8"> <input name="repoPassword" class="form-control" type="text"> </div> </div> <div class="form-group"> <label class="col-sm-3 control-label">db类型:</label> <div class="col-sm-8"> <select name="repoType" class="form-control m-b"> <option value="">所有</option> </select> <span class="help-block m-b-none"><i class="fa fa-info-circle"></i> 代码生成请选择字典属性</span> </div> </div> <div class="form-group"> <label class="col-sm-3 control-label">当资源库类型是db时候的连接类型:</label> <div class="col-sm-8"> <input name="dbAccess" class="form-control" type="text"> </div> </div> <div class="form-group"> <label class="col-sm-3 control-label">当资源库类型是db时候的ip:</label> <div class="col-sm-8"> <input name="dbHost" class="form-control" type="text"> </div> </div> <div class="form-group"> <label class="col-sm-3 control-label">当资源库类型是db时候的端口:</label> <div class="col-sm-8"> <input name="dbPort" class="form-control" type="text"> </div> </div> <div class="form-group"> <label class="col-sm-3 control-label">当资源库类型是db时候的db库名:</label> <div class="col-sm-8"> <input name="dbName" class="form-control" type="text"> </div> </div> <div class="form-group"> <label class="col-sm-3 control-label">当资源库类型是db时候的db用户名:</label> <div class="col-sm-8"> <input name="dbUsername" class="form-control" type="text"> </div> </div> <div class="form-group"> <label class="col-sm-3 control-label">当资源库类型是db时候的db用户密码:</label> <div class="col-sm-8"> <input name="dbPassword" class="form-control" type="text"> </div> </div> <div class="form-group"> <label class="col-sm-3 control-label">软删除:</label> <div class="col-sm-8"> <input name="isDel" class="form-control" type="text"> </div> </div> <div class="form-group"> <label class="col-sm-3 control-label">:</label> <div class="col-sm-8"> <div class="input-group date"> <input name="createdTime" class="form-control" placeholder="yyyy-MM-dd" type="text"> <span class="input-group-addon"><i class="fa fa-calendar"></i></span> </div> </div> </div> <div class="form-group"> <label class="col-sm-3 control-label">:</label> <div class="col-sm-8"> <input name="createdBy" class="form-control" type="text"> </div> </div>--> <div class="form-group"> <label class="col-sm-3 control-label">资源库类型:</label> <div class="col-sm-8"> <!-- <select name="type" class="form-control m-b"> <option value="">所有</option> </select>--> <select class="form-control" name="type" th:with="type=${@dict.getType('repository_type')}" disabled="disabled"> <option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}"></option> </select> </div> </div> <!-- <div class="form-group"> <label class="col-sm-3 control-label">基础路径:</label> <div class="col-sm-8"> <input name="baseDir" class="form-control" type="text"> </div> </div>--> <!-- 修改基础路径的表单组 --> <div class="modal fade" id="dirBrowserModal"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <h4 class="modal-title">选择服务器目录</h4> </div> <div class="modal-body"> <div class="list-group" id="dirListContainer"> <!-- 目录列表将通过JS动态加载 --> </div> <div class="current-path mt-2"> 当前路径: <span id="currentPath"></span> </div> </div> <div class="modal-footer"> <button type="button" class="btn btn-default" data-dismiss="modal">取消</button> <button type="button" class="btn btn-primary" id="btnSelectDir">选择当前目录</button> </div> </div> </div> </div> <!-- 修改基础路径字段 --> <div class="form-group"> <label class="col-sm-3 control-label">基础路径:</label> <div class="col-sm-8"> <div class="input-group"> <input id="baseDir" name="baseDir" class="form-control" type="text" readonly> <span class="input-group-btn"> <button class="btn btn-default" type="button" id="btn-browse-server-dir">浏览服务器目录</button> </span> </div> </div> </div> </form> </div> <th:block th:include="include :: footer"/> <th:block th:include="include :: datetimepicker-js"/> <script th:inline="javascript"> var prefix = ctx + "kettle/repository" $("#form-repository-add").validate({ focusCleanup: true }); function submitHandler() { if ($.validate.form()) { $.operate.save(prefix + "/add", $('#form-repository-add').serialize()); } } let currentBrowsingPath = ''; // 打开目录浏览器 $("#btn-browse-server-dir").click(function() { currentBrowsingPath = ''; loadDirectoryList(''); $("#dirBrowserModal").modal("show"); }); // 加载目录列表 function loadDirectoryList(path) { $.ajax({ url: prefix + "/browseDir", type: "get", data: { baseDir: path }, success: function(result) { if (result.code === 0) { renderDirectoryList(result.data); $("#currentPath").text(path || '/'); currentBrowsingPath = path; } else { $.modal.alertError(result.msg); } } }); } // 渲染目录列表 function renderDirectoryList(dirs) { const container = $("#dirListContainer"); container.empty(); dirs.forEach(dir => { const item = $(` <a href="javascript:void(0);" class="list-group-item directory-item" data-path="${dir.path}"> <i class="fa fa-folder"></i> ${dir.name} </a> `); container.append(item); }); // 添加点击事件 $(".directory-item").click(function() { const path = $(this).data("path"); loadDirectoryList(path); }); } // 选择当前目录 $("#btnSelectDir").click(function() { if (currentBrowsingPath) { $("#baseDir").val(currentBrowsingPath); $("#dirBrowserModal").modal("hide"); } else { $.modal.alertWarning("请先选择目录"); } }); // $("input[name='createdTime']").datetimepicker({ // format: "yyyy-mm-dd", // minView: "month", // autoclose: true // }); </script> </body> </html> 查到了目录路径,但是前端选不到,有灰色遮挡层,怎么调整
06-20
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值