基本成型

This commit is contained in:
JACKYMYPERSON
2025-09-27 17:24:52 +08:00
parent 578d49826b
commit eae49c76bd
502 changed files with 15238 additions and 708 deletions

View File

@@ -0,0 +1,26 @@
{
"component": true,
"navigationBarTitleText": "发布投票文章",
"usingComponents": {
"van-field": "@vant/weapp/field/index",
"van-radio": "@vant/weapp/radio/index",
"van-radio-group": "@vant/weapp/radio-group/index",
"van-icon": "@vant/weapp/icon/index",
"t-tabs": "tdesign-miniprogram/tabs/tabs",
"t-tab-panel": "tdesign-miniprogram/tab-panel/tab-panel",
"t-input": "tdesign-miniprogram/input/input",
"t-radio": "tdesign-miniprogram/radio/radio",
"t-radio-group": "tdesign-miniprogram/radio-group/radio-group",
"t-icon": "tdesign-miniprogram/icon/icon",
"t-cell": "tdesign-miniprogram/cell/cell",
"t-date-time-picker": "tdesign-miniprogram/date-time-picker/date-time-picker",
"t-button": "tdesign-miniprogram/button/button",
"t-picker": "tdesign-miniprogram/picker/picker",
"t-picker-item": "tdesign-miniprogram/picker-item/picker-item"
},
"navigationBarBackgroundColor": "#ffffff",
"navigationBarTextStyle": "black"
}

View File

@@ -0,0 +1,265 @@
Page({
data: {
// 表单数据(与需求字段对应)
form: {
title: "", // 文章标题
vote_type: "single", // 投票类型single-单选multiple-多选
end_time: "", // 结束时间ISO格式2025-10-22T00:59:59+08:00
end_time_format: "", // 结束时间展示用2025-10-22 00:59
options: [
{ content: "", sort_order: 1 }, // 默认1个选项sort_order自动生成
],
},
showTimePicker: false, // 时间选择器弹窗显隐
currentTime: new Date().getTime(), // 当前选择的时间
minDate: new Date().getTime(), // 最小可选时间(当前时间)
isSubmitting: false, // 提交状态
style: 'border: 2rpx solid var(--td-component-border);border-radius: 12rpx;',
value: 0,
value1: 0,
mode: '',
datetimeVisible: false,
datetime: new Date().getTime(),
datetimeText: '',
cityText: '',
cityValue: [],
citys: [
{ label: '用户邀请码', value: '用户邀请码' },
],
},
// 1. 输入框通用处理(标题)
handleInput(e) {
const { key } = e.currentTarget.dataset;
this.setData({
[`form.${key}`]: e.detail.value,
});
},
// 2. 投票类型切换(单选/多选)
handleVoteTypeChange(e) {
this.setData({
"form.vote_type": e.detail,
});
},
showPicker(e) {
console.log("截止")
const { mode } = e?.currentTarget?.dataset;
this.setData({
mode,
[`${mode}Visible`]: true,
});
console.log("截止2",mo)
},
hidePicker() {
const { mode } = this.data;
this.setData({
[`${mode}Visible`]: false,
});
},
onConfirm(e) {
const { value } = e?.detail;
const { mode } = this.data;
console.log('confirm', value);
this.setData({
[mode]: value,
[`${mode}Text`]: value,
});
this.hidePicker();
},
onColumnChange(e) {
console.log('pick', e?.detail?.value);
},
// 6. 投票选项输入
handleOptionInput(e) {
const { index, key } = e.currentTarget.dataset;
this.setData({
[`form.options[${index}].${key}`]: e.detail.value,
});
},
// 8. 删除投票选项至少保留1个
deleteOption(e) {
const { index } = e.currentTarget.dataset;
const { options } = this.data.form;
if (options.length <= 1) return;
// 删除后重新排序sort_order
const newOptions = options.filter((_, i) => i !== index);
newOptions.forEach((item, i) => {
item.sort_order = i + 1;
});
this.setData({
"form.options": newOptions,
});
},
// 9. 表单校验
validateForm() {
const { title, end_time, options } = this.data.form;
// 校验标题
if (!title.trim()) {
wx.showToast({ title: "请输入文章标题", icon: "none" });
return false;
}
// 校验结束时间
if (!end_time) {
wx.showToast({ title: "请选择投票结束时间", icon: "none" });
return false;
}
// 校验选项至少1个且内容不为空
const hasEmptyOption = options.some(
(item) => !item.content.trim()
);
if (hasEmptyOption) {
wx.showToast({ title: "请完善所有选项内容", icon: "none" });
return false;
}
return true;
},
// 10. 提交发布
handleSubmit() {
// 1. 表单校验
if (!this.validateForm()) return;
// 2. 整理提交数据(过滤空值,只保留需求字段)
const { title, vote_type, end_time, options } = this.data.form;
const submitData = {
title: title.trim(),
vote_type,
end_time,
options: options.map((item) => ({
content: item.content.trim(),
sort_order: item.sort_order,
})),
};
// 3. 模拟提交(替换为实际接口请求)
this.setData({ isSubmitting: true });
console.log("发布投票文章数据:", submitData);
// 模拟接口请求2秒后返回成功
setTimeout(() => {
wx.showToast({ title: "发布成功" });
this.setData({ isSubmitting: false });
// 发布成功后返回上一页
wx.navigateBack({ delta: 1 });
}, 2000);
},
onChange(e) {
this.setData({ value: e.detail.value });
},
onChange1(e) {
this.setData({ value1: e.detail.value });
},
addOption1() {
const { form } = this.data;
// 最多3个选项
if (form.options.length < 5) {
// 创建新数组并添加新选项(保持原有选项数据)
const newOptions = [...form.options];
newOptions.push({
content: "",
sort_order: newOptions.length + 1
});
this.setData({
'form.options': newOptions
});
}
},
// 删除选项
removeOption(e) {
const { index } = e.currentTarget.dataset;
const { form } = this.data;
if (form.options.length > 1) {
// 过滤掉要删除的选项,保留其他选项数据
let newOptions = form.options.filter((_, i) => i !== index);
// 重新排序(不影响内容,只更新序号)
newOptions = newOptions.map((item, i) => ({
...item, // 保留原有内容
sort_order: i + 1
}));
this.setData({
'form.options': newOptions
});
}
},
// 选项内容输入
onOptionInput(e) {
const { index } = e.currentTarget.dataset;
const { form } = this.data;
// 创建新数组避免直接修改原数据
const newOptions = [...form.options];
// 只更新当前输入的选项内容
newOptions[index].content = e.detail.value;
console.log("输入:",newOptions[index].content)
this.setData({
'form.options': newOptions
});
},
onColumnChange(e) {
console.log('picker pick:', e);
},
onPickerChange(e) {
const { key } = e.currentTarget.dataset;
const { value } = e.detail;
console.log('picker change:', e.detail);
this.setData({
[`${key}Visible`]: false,
[`${key}Value`]: value,
[`${key}Text`]: value.join(' '),
});
},
onPickerCancel(e) {
const { key } = e.currentTarget.dataset;
console.log(e, '取消');
console.log('picker1 cancel:');
this.setData({
[`${key}Visible`]: false,
});
},
onCityPicker() {
this.setData({ cityVisible: true });
},
onSeasonPicker() {
this.setData({ dateVisible: true });
},
});

View File

@@ -0,0 +1,149 @@
<view class="publish-page">
<!-- TDesign 选项卡:普通发布 / 内推码发布 -->
<t-tabs
defaultValue="{{0}}"
theme="card"
class="publish-tabs"
bind:change="handleTabChange"
>
<!-- 第一个选项卡:普通发布 -->
<t-tab-panel label="普通发布" value="{{0}}" class="tab-panel">
<view class="input-example">
<view class="input-example__label"> 标签文字 </view>
<t-input
placeholder="请输入文字"
borderless="{{true}}"
style="{{style}}"
/>
</view>
<view class="wenping-label"> 选择文评类型 </view>
<t-radio-group
t-class="horizontal-box"
value="{{value1}}"
bind:change="onChange1"
>
<view
wx:for="{{2}}"
wx:key="index"
class="card {{value1 == index ? 'card--active' : ''}}"
>
<!-- 选中时显示对勾图标 -->
<t-icon
wx:if="{{value1 == index}}"
name="check"
t-class="card__icon"
/>
<!-- 单选按钮(隐藏原生图标,用自定义样式替代) -->
<t-radio
value="{{index}}"
label="{{index == 0 ? '单选' : '多选'}}"
icon="none"
borderless
/>
</view>
</t-radio-group>
<view class="options-container">
<view class="options-header">
<view class="options-label">选项设置</view>
<t-button theme="primary" size="large" variant="text"
bindtap="addOption1" style="margin-left: 40vw;"
>添加选项</t-button>
</view>
<!-- 选项列表 - 绑定到form.options -->
<view class="options-list">
<view wx:for="{{form.options}}" wx:key="index" class="option-item">
<t-input
placeholder="请输入选项内容"
value="{{item.content}}"
bind:change="onOptionInput"
data-index="{{index}}"
class="option-input"
/>
<t-icon
name="delete"
size="24rpx"
class="delete-option"
bind:tap="removeOption"
data-index="{{index}}"
wx:if="{{form.options.length > 1}}"
/>
</view>
</view>
<view class="options-hint" wx:if="{{form.options.length > 0}}">
已添加 {{form.options.length}}/5 个选项
</view>
</view>
<t-cell
title="截止时间"
hover
note="{{datetimeText}}"
arrow
data-mode="datetime"
bindtap="showPicker"
t-class="panel-item"
/>
<!-- 年月日时分 -->
<t-date-time-picker
title="截止时间"
visible="{{datetimeVisible}}"
mode="second"
value="{{datetime}}"
format="YYYY-MM-DD HH:mm:ss"
bindchange="onConfirm"
bindpick="onColumnChange"
bindcancel="hidePicker"
/>
<view class="button-example">
<t-button theme="primary" size="large" block>发布文评</t-button>
</view>
</t-tab-panel>
<!-- 第二个选项卡:内推码发布 -->
<t-tab-panel label="内推码发布" value="{{1}}" class="tab-panel">
<t-form class="referral-publish-form" bind:submit="handleReferralSubmit">
<!-- 内推码发布表单内容 -->
<t-form-item label="公司名称" required>
<t-cell class="mb-16" title="选择内推码类型" arrow hover note="{{cityText}}" bind:click="onCityPicker" />
<t-picker
visible="{{cityVisible}}"
value="{{cityValue}}"
data-key="city"
title="选择内推码类型"
cancelBtn="取消"
confirmBtn="确认"
usingCustomNavbar
bindchange="onPickerChange"
bindpick="onColumnChange"
bindcancel="onPickerCancel"
>
<t-picker-item options="{{citys}}" format="{{formatter}}">
<block wx:for="{{citys}}" wx:key="index" wx:for-item="option">
<view wx:if="{{option.tag}}" slot="label-suffix--{{index}}" class="label-suffix">
<t-tag size="small" theme="primary">{{option.tag}}</t-tag>
</view>
</block>
</t-picker-item>
</t-picker>
</t-form-item>
<t-form-item>
<t-button type="primary" form-type="submit" class="submit-btn">
发布内推码
</t-button>
</t-form-item>
</t-form>
</t-tab-panel>
</t-tabs>
</view>

View File

@@ -0,0 +1,205 @@
/* 页面容器 */
.publish-page {
padding: 24rpx;
background-color: #f5f7fa;
min-height: 100vh;
box-sizing: border-box;
padding-bottom: 13vh;
}
/* Tabs 选项卡样式 */
.publish-tabs {
--tabs-card-height: 80rpx; /* 选项卡高度 */
--tabs-card-font-size: 28rpx; /* 选项卡文字大小 */
--tabs-card-active-color: #ffffff; /* 激活态文字色 */
--tabs-card-active-background-color: #1677ff; /* 激活态背景色 */
--tabs-card-inactive-color: #333333; /* 未激活文字色 */
--tabs-card-inactive-background-color: #ffffff; /* 未激活背景色 */
--tabs-card-border-radius: 12rpx; /* 选项卡圆角 */
margin-bottom: 24rpx;
}
/* 选项卡面板样式 */
.tab-panel {
background-color: #ffffff;
border-radius: 16rpx;
padding: 30rpx 24rpx;
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.03);
}
/* 普通发布表单样式 */
.common-publish-form,
.referral-publish-form {
width: 100%;
}
/* 表单项间距 */
.t-form-item {
margin-bottom: 30rpx !important;
}
/* 表单标签样式 */
.t-form-item__label {
font-size: 28rpx !important;
color: #333333 !important;
width: 160rpx !important; /* 固定标签宽度,对齐更整齐 */
}
/* 输入框样式 */
.t-input,
.t-textarea {
--input-height: 72rpx !important;
--input-font-size: 26rpx !important;
--input-placeholder-color: #999999 !important;
--input-border-radius: 10rpx !important;
}
/* 提交按钮样式 */
.submit-btn {
--button-height: 88rpx !important;
--button-font-size: 30rpx !important;
--button-primary-background-color: #1677ff !important;
--button-border-radius: 12rpx !important;
width: 100%;
}
.input-example {
--td-input-vertical-padding: 24rpx;
background-color: var(--bg-color-demo);
padding: 32rpx 32rpx 16rpx;
}
.input-example__label {
color: var(--td-text-color-primary);
font-size: 24rpx;
line-height: 40rpx;
margin: 0 8rpx 16rpx;
}
.card {
position: relative;
border-radius: 12rpx;
overflow: hidden;
box-sizing: border-box;
border: 3rpx solid var(--td-bg-color-container, #fff);
background-color: #c09d9d !important;
}
.card--active {
border-color: var(--td-brand-color, #0052d9);
}
.card--active::after {
content: '';
display: block;
position: absolute;
left: 0;
top: 0;
width: 0;
border-width: 28px 28px 28px 0;
border-style: solid;
border-color: var(--td-brand-color, #0052d9) transparent transparent transparent;
}
.card__icon {
color: var(--td-bg-color-container, #fff);
position: absolute;
left: 1.5px;
top: 1.5px;
z-index: 1;
}
/* 横向布局 */
.horizontal-box {
display: flex;
align-items: center;
justify-content: space-between;
flex-wrap: wrap;
margin: 32rpx;
}
.horizontal-box .card {
flex: 0 0 calc(50.33% - 12rpx);
margin: 0 0 24rpx 0;
}
.wenping-label{
margin-left: 5vw;
}
.wenping-label{
font-size: 24rpx;
}
/* 选项容器样式 */
.options-container {
margin-top: 40rpx;
padding: 24rpx;
background-color: #f9f9f9;
border-radius: 12rpx;
}
/* 选项头部 */
.options-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 24rpx;
}
.options-label {
font-size: 28rpx;
color: #333;
font-weight: 500;
}
.add-option-btn {
height: 56rpx;
line-height: 56rpx;
padding: 0 20rpx;
font-size: 24rpx;
}
/* 选项列表 */
.options-list {
display: flex;
flex-direction: column;
gap: 16rpx;
}
.option-item {
display: flex;
align-items: center;
gap: 16rpx;
background-color: #fff;
padding: 12rpx 16rpx;
border-radius: 8rpx;
border: 1px solid #eee;
}
.option-input {
flex: 1;
--input-height: 60rpx !important;
--input-font-size: 26rpx !important;
}
.delete-option {
color: #ff4d4f;
padding: 8rpx;
cursor: pointer;
}
/* 选项提示 */
.options-hint {
margin-top: 16rpx;
font-size: 22rpx;
color: #999;
text-align: right;
}
.submit-container{
width: 100%;
height: 20vh;
background: red;
}
.button-example {
margin: 32rpx;
}